<?php

namespace App\Services\Admin\Financial;

use App\Models\PaymentMeta;
use App\Models\Prefactor;
use App\Models\Setting;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;

class PrefactorsService
{
    /** get all prefactors list */
    public function getPrefactors(Request $request)
    {
        /** @var LengthAwarePaginator */
        $prefactors = Prefactor::query()->with('user')->when($request->input('search'), function ($query, $search) {
            $query->where('uuid', 'like', "%{$search}%");
        })->when($request->input('paid'), function ($query, $paid) {
            if ($paid) {
                $query->where('status', 'paid');
            }
        })->when($request->input('waiting_payment'), function ($query, $waiting_payment) {
            if ($waiting_payment) {
                $query->where('status', 'waiting_payment');
            }
        })->orderBy('created_at', 'desc')->paginate(20)->through(fn($prefactor) => [
            'id' => $prefactor->id,
            'uuid' => $prefactor->uuid,
            'title' => $prefactor->title,
            'get_by' => $prefactor->get_by,
            'is_expired' => $prefactor->is_expired,
            'jalali_expired_at' => $prefactor->jalali_expired_at,
            'jalali_created_at' => $prefactor->jalali_created_at,
            'status' => $prefactor->status,
            'user' => [
                'id' => $prefactor->user->id,
                'get_name' => $prefactor->user->get_name,
            ],
        ]);
        $prefactors->withQueryString();

        return $prefactors;
    }

    /** get prefactor order */
    public function getPrefactorOrder(Prefactor $prefactor)
    {
        $consignmentItems = [];
        $totalPrice = 0;
        $totalDiscount = 0;
        $totalFinalPrice = 0;
        $customerClubScore = 0;

        /** @var \App\Models\Order $order */
        $order = $prefactor->order;

        // get order consignment
        $consignments = [];
        if ($order != null) {
            $consignments = $order->consignments()->with('consignmentItems')->get();
        }

        // add consignment items
        $consignmentItems = new Collection();
        foreach ($consignments as $consignment) {
            $consignmentItems = $consignmentItems->merge($consignment->consignmentItems()->get());
        }

        // main store post ways status
        $mainStorePaymentMetaStatus = false;
        $mainStorePaymentMeta = PaymentMeta::where('store_id', null)->first();
        if ($mainStorePaymentMeta != null && $mainStorePaymentMeta->post_ways != null &&  count(unserialize($mainStorePaymentMeta->post_ways)) > 0) {
            $postWays = unserialize($mainStorePaymentMeta->post_ways);
            $hasActive = collect($postWays)->contains(function ($item) {
                return $item['status'] === true;
            });
            $mainStorePaymentMetaStatus = $hasActive;
        }

        // sync consignmentItems count
        foreach ($consignmentItems as $consignmentItem) {
            if ($consignmentItem->store != null && $consignmentItem->store->direct_post && !$consignmentItem->store->transportation_status) {
                $consignmentItem->delete();

                // update consignment items
                $consignmentItems = new Collection();
                foreach ($consignments as $consignment) {
                    $consignmentItems = $consignmentItems->merge($consignment->consignmentItems()->get());
                }
            } else if (!$mainStorePaymentMetaStatus) {
                $consignmentItem->delete();

                // update consignment items
                $consignmentItems = new Collection();
                foreach ($consignments as $consignment) {
                    $consignmentItems = $consignmentItems->merge($consignment->consignmentItems()->get());
                }
            }

            $inventory = $consignmentItem->inventory;
            if ($inventory->count == 0) {
                $consignmentItem->delete();

                // update consignment items
                $consignmentItems = new Collection();
                foreach ($consignments as $consignment) {
                    $consignmentItems = $consignmentItems->merge($consignment->consignmentItems()->get());
                }
            } else if ($consignmentItem->count > $inventory->count) {
                $consignmentItem->update([
                    'count' => $inventory->count
                ]);
            }
        }

        // discount code price
        $discountCode = $order->get_discount;
        $discountCodeAmount = $discountCode != null ? $discountCode['amount'] : 0;

        // prices
        $totalPrice = $consignmentItems->sum('get_full_count_price') + $consignmentItems->sum('get_full_count_discount');
        $totalDiscount = $consignmentItems->sum('get_full_count_discount');
        $totalFinalPrice = $consignmentItems->sum('get_full_count_price') - $discountCodeAmount;

        // get customer club (price and score)
        $customerClub = Setting::where('key', 'customer_club')->first();
        $customerClub = $customerClub != null ? unserialize($customerClub->value) : ['price' => 0, 'score' => 0];
        $customerClubScore = $customerClub['price'] > 0 && $customerClub['score'] > 0 ? round((($totalFinalPrice + $discountCodeAmount) / str_replace(',', '', $customerClub['price'])) * str_replace(',', '', $customerClub['score'])) : 0;

        return [
            'items' => fn() => $consignmentItems != null ? $consignmentItems->map(fn($item) => [
                'id' => $item->id,
                'get_props' => $item->get_props,
                'inventory_id' => $item->inventory_id,
                'count' => $item->count,
                'discount' => $item->discount,
                'price' => $item->price,

                'product' => [
                    'id' => $item->product->id,
                    'title' => $item->product->title,
                    'slug' => $item->product->slug,
                    'get_images' => $item->product->get_images,
                ],
                'store' => $item->store != null ? [
                    'id' => $item->store->id,
                    'uuid' => $item->store->uuid,
                    'name' => $item->store->name,
                ] : null,
            ]) : [],
            'totalPrice' => $totalPrice,
            'totalDiscount' => $totalDiscount,
            'discountCode' => $order->get_discount,
            'totalFinalPrice' => $totalFinalPrice,
            'customerClubScore' => $customerClubScore,
        ];
    }

    /** get prefactor order group */
    public function getPrefactorOrderGroup(Prefactor $prefactor)
    {
        $og = $prefactor->orderGroup;
        $orderGroup = [
            'id' => $og->id,
            'transaction_id' => $og->transaction_id,
            'uuid' => $og->uuid,
            'status' => $og->status,
            'jalali_created_at' => $og->jalali_created_at,
            'jalali_updated_at' => $og->jalali_updated_at,
            'user' => [
                'id' => $og->user->id,
                'get_name' => $og->user->get_name,
            ],
            'orders' => $og->orders->map(fn($order) => [
                'id' => $order->id,
                'transaction_id' => $order->transaction_id,
                'uuid' => $order->uuid,
                'send_by' => $order->send_by,
                'get_send_by' => $order->get_send_by,
                'is_awaiting_request_from_seller' => $order->is_awaiting_request_from_seller,
                'is_awaiting_seller' => $order->is_awaiting_seller,
                'is_awaiting_receipt_from_seller' => $order->is_awaiting_receipt_from_seller,
                'is_ready_to_send' => $order->is_ready_to_send,
                'is_all_item_cancelled' => $order->is_all_item_cancelled,
                'status' => $order->status,
                'jalali_created_at' => $order->jalali_created_at,
                'jalali_updated_at' => $order->jalali_updated_at,
            ]),
        ];

        return $orderGroup;
    }
}
