<?php

namespace Modules\Inventory\Repositories;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Modules\Core\Enums\SearchTypeEnum;
use Modules\Core\Enums\StatusEnum;
use Modules\Inventory\DTO\ProductListFilter;
use Modules\Inventory\Models\Category;
use Modules\Inventory\Models\Product;
use Modules\Inventory\Models\PurchaseInvoiceItem;
use Modules\Inventory\Models\Stock;
use Modules\Inventory\Models\Traits\GeneratesProductSku;

class ProductRepository
{
    use GeneratesProductSku;

    public function getProducts(ProductListFilter $filter, array $columns = ['*'], array $relations = []): LengthAwarePaginator
    {
        return Product::query()
            ->select($columns)
            ->with($relations)
            ->search($filter->search)
            ->when($filter->status, function ($q, $status) {
                $q->where('status', $status);
            })
            ->when($filter->inventory_department_id, function ($q, $deptId) {
                $q->where('inventory_department_id', $deptId);
            })
            ->when($filter->category_id, function ($q, $catId) {
                $q->where('category_id', $catId);
            })
            ->orderBy('id', 'desc')
            ->paginate($filter->perPage ?? 15);
    }

    public function find(int $id, array $relations = []): Product
    {
        return Product::query()
            ->with($relations)
            ->findOrFail($id);
    }

    public function create(array $data): Product
    {
        return Product::query()->create($data);
    }

    public function update(Product $product, array $data): Product
    {
        $product->update($data);

        return $product;
    }

    public function updateStatus(Product $product, array $status): Product
    {
        $product->update([
            'status' => $status['status'] ?? StatusEnum::ACTIVE,
        ]);

        return $product;
    }

    public function getCategory(int $id)
    {
        return Category::findOrFail($id);
    }

    public function hasTransactions(int $productId): bool
    {
        return
            Stock::where('product_id', $productId)->exists()
            || PurchaseInvoiceItem::where('product_id', $productId)->exists();
    }

    public function search(SearchTypeEnum $type, ?string $search, array $columns = ['*'])
    {
        $query = Product::query();

        match ($type) {
            SearchTypeEnum::PURCHASE => $query->purchaseProducts()->withPurchaseRelations(),
            SearchTypeEnum::ASSET_PURCHASE => $query->assetProducts()->withPurchaseRelations(),
            SearchTypeEnum::BILLING => $query->saleProducts()->withSaleRelations(),
        };

        return $query->search($search)->select($columns)->limit(20)->get();
    }
}
