<?php

namespace App\Http\Controllers\Api\Public;

use App\Http\Controllers\Controller;
use App\Http\Resources\ProductResource;
use App\Models\Product;
use App\Models\Rating;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ProductController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $request->validate([
            'category_id'    => 'nullable|exists:categories,id',
            'vendor_id'      => 'nullable|exists:vendors,id',
            'min_price'      => 'nullable|numeric|min:0',
            'max_price'      => 'nullable|numeric|min:0',
            'min_rating'     => 'nullable|numeric|min:0|max:5',
            'in_stock'       => 'nullable|boolean',
            'featured'       => 'nullable|boolean',
            'q'              => 'nullable|string|max:120',
            'sort'           => 'nullable|in:relevance,newest,price_asc,price_desc,rating,popular',
            'per_page'       => 'nullable|integer|min:5|max:60',
        ]);

        $query = Product::query()
            ->where('is_active', true)
            ->whereHas('vendor', fn($q) => $q->where('status', 'active'))
            ->with(['images', 'vendor', 'category']);

        // Category filter matches the whole subtree, so picking "Electronic
        // Devices" returns products attached to any leaf beneath it.
        if ($request->filled('category_id')) {
            $category = \App\Models\Category::find($request->category_id);
            if ($category) {
                $query->whereIn('category_id', $category->subtreeIds());
            }
        }

        if ($request->filled('vendor_id')) {
            $query->where('vendor_id', $request->vendor_id);
        }

        if ($request->filled('min_price')) {
            $query->where('price', '>=', $request->min_price);
        }

        if ($request->filled('max_price')) {
            $query->where('price', '<=', $request->max_price);
        }

        if ($request->filled('min_rating')) {
            $query->where('rating_average', '>=', $request->min_rating);
        }

        if ($request->boolean('in_stock')) {
            $query->where(fn($q) => $q->where('track_stock', false)->orWhere('stock_quantity', '>', 0));
        }

        if ($request->boolean('featured')) {
            $query->where('is_featured', true);
        }

        // Attribute facet filters: ?attr[brand]=Apple&attr[color]=Black,Red
        // AND across attributes, OR within a single attribute's values.
        foreach ((array) $request->input('attr', []) as $slug => $vals) {
            $values = array_filter(array_map('trim', is_array($vals) ? $vals : explode(',', (string) $vals)));
            if (empty($values)) {
                continue;
            }
            $query->whereHas('attributeValues', function ($q) use ($slug, $values) {
                $q->whereIn('value', $values)
                    ->whereHas('attribute', fn($a) => $a->where('slug', $slug));
            });
        }

        if ($request->filled('q')) {
            $term = $request->q;
            $query->where(fn($q) => $q
                ->where('name_en', 'like', "%{$term}%")
                ->orWhere('name_ur', 'like', "%{$term}%")
                ->orWhere('description_en', 'like', "%{$term}%"));
        }

        // Sort by the price the customer actually sees (discounted when present).
        match ($request->input('sort', 'newest')) {
            'newest'     => $query->latest(),
            'price_asc'  => $query->orderByRaw('COALESCE(discount_price, price) ASC'),
            'price_desc' => $query->orderByRaw('COALESCE(discount_price, price) DESC'),
            'rating'     => $query->orderByDesc('rating_average'),
            'popular'    => $query->orderByDesc('order_count'),
            default      => $query->latest(),
        };

        $products = $query->paginate($request->integer('per_page', 20));

        return ProductResource::collection($products)->response();
    }

    public function show(string $slug): JsonResponse
    {
        $product = Product::where('slug', $slug)
            ->where('is_active', true)
            ->with(['images', 'variants', 'vendor.category', 'category.parent.parent', 'attributeValues.attribute'])
            ->firstOrFail();

        // Track view (fire-and-forget)
        $product->increment('view_count');

        return response()->json([
            'data' => new ProductResource($product),
        ]);
    }

    /** GET /products/{slug}/reviews — customer reviews for a product. */
    public function reviews(string $slug, Request $request): JsonResponse
    {
        $product = Product::where('slug', $slug)->firstOrFail();

        $base = Rating::where('rateable_type', Product::class)
            ->where('rateable_id', $product->id)
            ->where('is_hidden', false);

        $counts = (clone $base)->selectRaw('stars, COUNT(*) as c')->groupBy('stars')->pluck('c', 'stars');
        $distribution = [];
        $total = 0;
        $weighted = 0;
        for ($s = 5; $s >= 1; $s--) {
            $n = (int) ($counts[$s] ?? 0);
            $distribution[$s] = $n;
            $total += $n;
            $weighted += $s * $n;
        }

        $reviews = (clone $base)
            ->with('user:id,name')
            ->orderByRaw('(comment IS NULL OR comment = "") asc')
            ->latest()
            ->paginate($request->integer('per_page', 10));

        $reviews->getCollection()->transform(fn($r) => [
            'id'       => $r->id,
            'stars'    => $r->stars,
            'comment'  => $r->comment,
            'user'     => $r->user?->name ? Str::of($r->user->name)->explode(' ')->first() : 'Customer',
            'verified' => (bool) $r->is_verified_purchase,
            'date'     => $r->created_at?->toIso8601String(),
        ]);

        return response()->json([
            'summary' => [
                'average'      => $total ? round($weighted / $total, 1) : 0,
                'count'        => $total,
                'distribution' => $distribution,
            ],
            'data' => $reviews->items(),
            'meta' => [
                'current_page' => $reviews->currentPage(),
                'last_page'    => $reviews->lastPage(),
                'total'        => $reviews->total(),
            ],
        ]);
    }

    public function featured(): JsonResponse
    {
        $products = Product::where('is_active', true)
            ->where('is_featured', true)
            ->whereHas('vendor', fn($q) => $q->where('status', 'active'))
            ->with(['images', 'vendor'])
            ->orderByDesc('rating_average')
            ->limit(12)
            ->get();

        return response()->json([
            'data' => ProductResource::collection($products),
        ]);
    }
}
