<?php

namespace App\Repositories;

use App\Models\Order;

class OrderRepository
{
    public function __construct(public Order $order)
    {
    }

    /**
     * @throws \Exception
     */
    public function create(array $orderData)
    {
        return $this->order->create($orderData);
    }

    public function update($order, $key, $value): void
    {
        $order->update([$key => $value]);
    }

    public function getOrderById($id, $userId = null)
    {
        return $this->order::query()
            ->where('id', $id)
            ->when($userId, fn($query) => $query->where('user_id', $userId))
            ->first();
    }

    public function getOrderByEncryptedId($id)
    {
        $id = decryptId($id);

        return $this->order::query()
            ->where('id', $id)
            ->first();
    }

    public function all($perPage)
    {
        return $this->order->orderByDesc('id')->paginate($perPage);
    }

    public function paginateOneTimeOrders($perPage)
    {
        return $this->order->whereNull('subscription_id')->orderByDesc('id')->paginate($perPage);
    }

    public function filter($searchTerm, $status, $userId, $discountCode, $paymentMethod, $perPage)
    {
        $query = $this->order->newQuery();

        if ($searchTerm) {
            $query->where('order_reference', 'LIKE', '%' . $searchTerm . '%');
        }

        if ($status !== null) {
            $query->where('status', $status);
        }

        if ($userId) {
            $query->where('user_id', $userId);
        }

        if ($discountCode) {
            $query->where('discount_code', $discountCode);
        }

        if ($paymentMethod) {
            $query->where('payment_method', $paymentMethod);
        }

        return $query->paginate($perPage);
    }

    public function filterOneTimeOrders($searchTerm, $status, $userId, $discountCode, $paymentMethod, $perPage)
    {
        $query = $this->order->whereNull('subscription_id')->newQuery();

        if ($searchTerm) {
            $query->where('order_reference', 'LIKE', '%' . $searchTerm . '%');
        }

        if ($status !== null) {
            $query->where('status', $status);
        }

        if ($userId) {
            $query->where('user_id', $userId);
        }

        if ($discountCode) {
            $query->where('discount_code', $discountCode);
        }

        if ($paymentMethod) {
            $query->where('payment_method', $paymentMethod);
        }

        return $query->paginate($perPage);
    }

    public function getAllOrders()
    {
        return $this->order->all();
    }

    public function getBySubscription($id)
    {
        return $this->order->where('subscription_id', $id)->first();
    }

    public function getOneTimeOrders()
    {
        return $this->order->whereNull('subscription_id')->get();
    }

    public function getOrderCountByStatus(array $statuses): array
    {
        return $this->order->newQuery()
            ->whereIn('status', $statuses)
            ->selectRaw('status, COUNT(*) as count')
            ->groupBy('status')
            ->pluck('count', 'status')
            ->toArray();
    }

    public function getOrderStatusCounts()
    {
        $orders = $this->order->all();

        $statusCounts = $orders->groupBy('status')->map(function ($group) {
            return $group->count();
        });

        return $statusCounts;
    }

    public function getOneTimeOrderStatusCounts()
    {
        $orders = $this->order->whereNull('subscription_id')->get();

        $statusCounts = $orders->groupBy('status')->map(function ($group) {
            return $group->count();
        });

        return $statusCounts;
    }

    public function deleteOrders(array $data)
    {
        $orders = $this->order->whereIn('id', $data['item_ids'])->get();

        foreach ($orders as $order) {
            $order->delete();
        }

        return true;
    }
}
