<?php

namespace App\Services;

use App\Models\Product;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;

class ProductServices
{
    public function getProductData(
        int $page,
        int $length,
        ?string $searchValue = null,
        ?string $status = null,
        ?int $companyId = null
    ): LengthAwarePaginator {
        $query = Product::query()
            ->leftJoin('supplier', 'supplier.id', '=', 'product.supplier_id')
            ->leftJoin('product_category', 'product_category.id', '=', 'product.category_id')
            ->select([
                'product.id',
                'product.product_name',
                'product.description',
                'product.sale_price',
                'product.purchase_price',
                'product.current_stock',
                'product.minimum_stock',
                'product.barcode',
                'product.is_active',
                'product.supplier_id',
                'product.category_id',
                'product.created_at',
                'supplier.supplier_name',
                'product_category.category_name',
            ])
            ->orderByDesc('product.id');

        if ($companyId !== null && $companyId > 0) {
            $query->where('product.company_id', $companyId);
        }

        if (! empty($searchValue)) {
            $query->where(function ($subQuery) use ($searchValue): void {
                $subQuery->where('product.product_name', 'like', "%{$searchValue}%")
                    ->orWhere('product.description', 'like', "%{$searchValue}%")
                    ->orWhere('product.barcode', 'like', "%{$searchValue}%")
                    ->orWhere('supplier.supplier_name', 'like', "%{$searchValue}%")
                    ->orWhere('product_category.category_name', 'like', "%{$searchValue}%");
            });
        }

        $paginator = $query->paginate($length, ['*'], 'page', $page);

        $paginator->getCollection()->transform(function ($product) {
            return [
                'id' => $product->id,
                'product_name' => $product->product_name,
                'description' => $product->description,
                'sale_price' => number_format((float) $product->sale_price, 2, ',', '.'),
                'purchase_price' => number_format((float) $product->purchase_price, 2, ',', '.'),
                'current_stock' => (int) $product->current_stock,
                'minimum_stock' => (int) $product->minimum_stock,
                'barcode' => $product->barcode,
                'is_active' => (int) ($product->is_active ?? 0),
                'supplier_name' => $product->supplier_name ?: 'N/A',
                'category_name' => $product->category_name ?: 'N/A',
                'created_at_formatted' => $product->created_at?->format('d/m/Y H:i'),
            ];
        });

        return $paginator;
    }

    public function createProduct(Request $request, int $companyId): Product
    {
        $validated = $this->validateProductRequest($request);
        $validated['current_stock'] = 0;
        $validated['company_id'] = $companyId;

        return Product::create($validated);
    }

    public function updateProduct(Request $request, Product $product): Product
    {
        $validated = $this->validateProductRequest($request, $product);
        unset($validated['current_stock']);

        $product->update($validated);

        return $product->refresh();
    }

    public function deleteProduct(Product $product): void
    {
        $product->delete();
    }

    public function setIsActive(Product $product, bool $isActive): Product
    {
        $product->is_active = $isActive;
        $product->save();

        return $product->refresh();
    }

    public function getSupplierOptions()
    {
        return DB::table('supplier')
            ->select('id', 'supplier_name')
            ->orderBy('supplier_name')
            ->get();
    }

    public function getCategoryOptions()
    {
        return DB::table('product_category')
            ->select('id', 'category_name')
            ->where('is_active', 1)
            ->orderBy('category_name')
            ->get();
    }

    private function validateProductRequest(Request $request, ?Product $product = null): array
    {
        $productId = $product?->id;

        return $request->validate([
            'product_name' => ['required', 'string', 'max:255'],
            'description' => ['nullable', 'string', 'max:255'],
            'sale_price' => ['required', 'numeric', 'min:0'],
            'purchase_price' => ['required', 'numeric', 'min:0'],
            'minimum_stock' => ['nullable', 'integer', 'min:0'],
            'barcode' => ['nullable', 'string', 'max:100', Rule::unique('product', 'barcode')->ignore($productId)],
            'supplier_id' => ['nullable', 'integer', 'exists:supplier,id'],
            'category_id' => ['nullable', 'integer', 'exists:product_category,id'],
        ]);
    }
}
