<?php

namespace App\Services\Admin\Users;

use App\Models\PaymentMeta;
use App\Models\Product;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class UsersService
{
    /** get users list */
    public function getUsers(Request $request)
    {
        /** @var LengthAwarePaginator */
        $users = User::query()->when($request->input('search'), function ($query, $search) {
            $query->where(DB::raw('concat(`username`, `phone`)'), 'like', "%{$search}%");
        })->when($request->input('active'), function ($query, $active) {
            if ($active) {
                $query->where('status', 'active');
            }
        })->when($request->input('banned'), function ($query, $banned) {
            if ($banned) {
                $query->where('status', 'banned');
            }
        })->when($request->input('admin'), function ($query, $admin) {
            if ($admin) {
                $query->where('type', 'admin');
            }
        })->when($request->input('seller'), function ($query, $seller) {
            if ($seller) {
                $query->where('seller', true)->where('type', '!=', 'admin');
            }
        })->when($request->input('user'), function ($query, $user) {
            if ($user) {
                $query->where('type', 'user')->where('seller', false);
            }
        })->orderBy('created_at', 'desc')->with('wallet')->paginate(20)->through(fn($user) => [
            'id' => $user->id,
            'get_avatar' => $user->get_avatar,
            'get_name' => $user->get_name,
            'phone' => $user->phone,
            'username' => $user->username,
            'type' => $user->type,
            'seller' => $user->seller,
            'jalali_created_at' => $user->jalali_created_at,
            'status' => $user->status,

            'role' => $user->role != null ? $user->role : null,
            'wallet' => [
                'id' => $user->wallet->id,
                'get_formatted_amount' => $user->wallet->get_formatted_amount,
            ]
        ]);

        $users->withQueryString();

        return $users;
    }

    /** get user cart list */
    public function getUserCart(User $user)
    {
        $consignmentItems = [];
        $totalPrice = 0;
        $totalDiscount = 0;
        $totalFinalPrice = 0;
        $customerClubScore = 0;

        if ($user != null) {
            /** @var \App\Models\Order $order */
            $order = $user->orders()->where('status', 'awaiting')->first();

            // 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 != null) {
                    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
                        ]);
                    }
                } else {
                    $consignmentItem->delete();
                }
            }

            // 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');

            // 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(($consignmentItems->sum('get_full_count_price') / 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,
            'totalFinalPrice' => $totalFinalPrice,
            'customerClubScore' => $customerClubScore,
        ];
    }

    /** get user order list */
    public function getUserOrders(User $user)
    {
        /** @var LengthAwarePaginator */
        $orders = $user->orders()->where('status', '!=', 'prefactor')->where('status', '!=', 'awaiting')->orderByRaw("FIELD(status , 'registered') DESC")->orderBy('created_at', 'desc')->paginate(20);

        $orders = $orders->through(fn($order) => [
            'id' => $order->id,
            'transaction_id' => $order->transaction_id,
            'uuid' => $order->uuid,
            'status' => $order->status,
            'jalali_created_at' => $order->jalali_created_at,
            'jalali_updated_at' => $order->jalali_updated_at,
        ]);

        $orders->withQueryString();

        return $orders;
    }

    /** get user transactions list */
    public function getUserTransactions(User $user)
    {
        /** @var LengthAwarePaginator */
        $transactions = $user->transactions()->orderBy('created_at', 'desc')->paginate(20)->through(fn($transaction) => [
            'id' => $transaction->id,
            'amount' => $transaction->amount,
            'type' => $transaction->type,
            'get_formatted_amount' => $transaction->get_formatted_amount,
            'description' => $transaction->description,
            'transaction_id' => $transaction->transaction_id,
            'jalali_created_at' => $transaction->jalali_created_at,
            'status' => $transaction->status,
        ]);
        $transactions->withQueryString();

        return $transactions;
    }

    /** get user tickets list */
    public function getUserTickets(User $user)
    {
        /** @var LengthAwarePaginator */
        $tickets = $user->tickets()->orderByRaw("FIELD(status , 'waiting_admin', 'waiting_user', 'closed') ASC")
            ->orderByRaw("FIELD(priority , 'high', 'normal', 'low') ASC")
            ->orderBy('updated_at', 'asc')->paginate(10, ['*'], 'tpage')->through(fn($ticket) => [
                'id' => $ticket->id,
                'title' => $ticket->title,
                'priority' => $ticket->priority,
                'jalali_updated_at' => $ticket->jalali_updated_at,
                'status' => $ticket->status,
            ]);

        return $tickets;
    }

    /** get user tickets list */
    public function getUserProductComments(User $user)
    {
        /** @var LengthAwarePaginator */
        $comments = $user->productComments()->where('status', 'publish')->latest()->paginate(5, ['*'], 'pcpage')->through(fn($comment) => [
            'id' => $comment->id,
            'user_id' => $comment->user_id,
            'content' => $comment->content,
            'get_strengths' => $comment->get_strengths,
            'get_weakness' => $comment->get_weakness,
            'get_answer' => $comment->get_answer,
            'reported' => $comment->reported,
            'vote_up' => $comment->vote_up,
            'vote_down' => $comment->vote_down,
            'rating' => $comment->rating,
            'jalali_created_at' => $comment->jalali_created_at,
            'buy_suggest' => $comment->buy_suggest,
            'status' => $comment->status,

            'product' => [
                'id' => $comment->product->id,
                'title' => $comment->product->title,
                'slug' => $comment->product->slug,
            ],
            'user' => [
                'id' => $comment->user->id,
                'get_name' => $comment->user->get_name,
                'type' => $comment->user->type
            ],
        ]);

        return $comments;
    }
}
