<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\V1\Shop;

use App\Http\Controllers\Controller;
use App\Models\Product;
use App\Models\ProductCategory;
use App\Services\Shop\ProductService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class ProductController extends Controller
{
    public function __construct(private readonly ProductService $service) {}

    public function index(Request $request): JsonResponse
    {
        $q = Product::query()->where('status', 'active');

        if ($cat = $request->query('category')) {
            $catId = ProductCategory::where('slug', $cat)->value('id');
            if ($catId) $q->where('category_id', $catId);
        }
        if ($search = $request->query('q')) {
            $q->where('name', 'like', "%{$search}%");
        }
        if ($minP = $request->query('min_price')) {
            $q->where('price', '>=', (int) $minP);
        }
        if ($maxP = $request->query('max_price')) {
            $q->where('price', '<=', (int) $maxP);
        }

        $sort = $request->query('sort', 'recent');
        match ($sort) {
            'price_asc' => $q->orderBy('price'),
            'price_desc' => $q->orderByDesc('price'),
            'name' => $q->orderBy('name'),
            default => $q->orderByDesc('created_at'),
        };

        return response()->json(['data' => $q->paginate((int) $request->query('per_page', 20))]);
    }

    public function show(string $slug): JsonResponse
    {
        $p = Product::with(['category', 'variants', 'images'])
            ->where('slug', $slug)
            ->firstOrFail();

        $related = Product::where('category_id', $p->category_id)
            ->where('id', '!=', $p->id)
            ->where('status', 'active')
            ->limit(6)
            ->get(['id', 'slug', 'name', 'price', 'sale_price', 'thumb_url']);

        return response()->json(['data' => $p, 'related' => $related]);
    }

    public function store(Request $request): JsonResponse
    {
        $this->authorizeAdmin($request);

        $data = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'slug' => ['nullable', 'string', 'max:191'],
            'description' => ['nullable', 'string'],
            'category_id' => ['nullable', 'uuid'],
            'brand' => ['nullable', 'string', 'max:120'],
            'sku' => ['nullable', 'string', 'max:80'],
            'price' => ['required', 'integer', 'min:0'],
            'sale_price' => ['nullable', 'integer', 'min:0'],
            'currency' => ['nullable', 'string', 'max:8'],
            'stock_qty' => ['nullable', 'integer', 'min:0'],
            'status' => ['nullable', Rule::in(['draft', 'active', 'out_of_stock', 'discontinued'])],
            'thumb_url' => ['nullable', 'string', 'max:500'],
            'meta' => ['nullable', 'array'],
        ]);

        return response()->json(['data' => $this->service->create($data)], 201);
    }

    public function update(Request $request, string $id): JsonResponse
    {
        $this->authorizeAdmin($request);
        $p = Product::findOrFail($id);

        $data = $request->validate([
            'name' => ['sometimes', 'string', 'max:255'],
            'description' => ['sometimes', 'string'],
            'category_id' => ['sometimes', 'uuid'],
            'price' => ['sometimes', 'integer', 'min:0'],
            'sale_price' => ['sometimes', 'nullable', 'integer', 'min:0'],
            'stock_qty' => ['sometimes', 'integer', 'min:0'],
            'status' => ['sometimes', Rule::in(['draft', 'active', 'out_of_stock', 'discontinued'])],
            'thumb_url' => ['sometimes', 'string', 'max:500'],
        ]);

        return response()->json(['data' => $this->service->update($p, $data)]);
    }

    public function destroy(Request $request, string $id): JsonResponse
    {
        $this->authorizeAdmin($request);
        $p = Product::findOrFail($id);
        $p->delete();
        return response()->json(['data' => ['id' => $id, 'deleted' => true]]);
    }

    public function categories(): JsonResponse
    {
        return response()->json(['data' => ProductCategory::orderBy('sort_order')->orderBy('name')->get()]);
    }

    private function authorizeAdmin(Request $request): void
    {
        $u = $request->user();
        if (! $u) abort(401);
        if (! $u->hasRole('super_admin') && ! $u->hasRole('tenant_admin') && ! $u->can('pages.update')) {
            abort(403);
        }
    }
}
