<?php

declare(strict_types=1);

namespace App\Services\AiAssistant\Tools;

use App\Models\Category;
use App\Models\Product;
use App\Services\AiAssistant\AiComponentRenderer;
use App\Services\AiAssistant\StructuredResponse;
use Laravel\Scout\Builder;

class CategoryTools
{
    public function __construct(
        protected AiComponentRenderer $renderer
    ) {}

    public function list(string $search = '', int $limit = 10): StructuredResponse
    {
        $scoutDriver = config('scout.driver');

        if ($scoutDriver === 'meilisearch' && $search !== '') {
            $categories = $this->searchWithMeilisearch($search);
        } else {
            $categories = $this->searchWithDatabase($search, $limit);
        }

        if ($categories->isEmpty()) {
            return StructuredResponse::fromText(
                $search
                    ? "No categories found matching '{$search}'."
                    : 'No categories available.'
            );
        }

        $text = $search
            ? "**Categories matching '{$search}'** ({$categories->count()}):\n\n"
            : "**Top {$categories->count()} Categories by Product Count**:\n\n";

        foreach ($categories as $index => $category) {
            if ($search) {
                $text .= "- **{$category->name_en}** (ID: {$category->id})";
            } else {
                $text .= ($index + 1).". **{$category->name_en}** (ID: {$category->id})";
            }
            $text .= " - {$category->products_count} product".($category->products_count === 1 ? '' : 's')."\n";
        }

        $html = $this->renderer->categoryGrid($categories);

        return StructuredResponse::withHtml($text, $html, [
            'count' => $categories->count(),
            'search' => $search,
        ]);
    }

    /**
     * Search categories using Meilisearch.
     * Only returns categories that have products.
     */
    protected function searchWithMeilisearch(string $search): \Illuminate\Database\Eloquent\Collection
    {
        /** @var Builder $searchQuery */
        $searchQuery = Category::search($search);

        $rawResults = $searchQuery->take(50)->raw();
        $categoryIds = collect($rawResults['hits'] ?? [])->pluck('id');

        if ($categoryIds->isEmpty()) {
            return collect();
        }

        return Category::withCount('products')
            ->whereHas('products')
            ->whereIn('id', $categoryIds)
            ->get()
            ->sortBy(fn ($c) => $categoryIds->search($c->id))
            ->values();
    }

    /**
     * Fallback database search for categories.
     * Only returns categories that have products, sorted by product count.
     */
    protected function searchWithDatabase(string $search, int $limit = 10): \Illuminate\Database\Eloquent\Collection
    {
        return Category::withCount('products')
            ->whereHas('products')
            ->when($search, fn ($q) => $q->where(function ($subQ) use ($search) {
                $subQ->where('name_en', 'like', "%{$search}%")
                    ->orWhere('name_ar', 'like', "%{$search}%");
            }))
            ->orderByDesc('products_count')
            ->limit($limit)
            ->get();
    }

    public function getProducts(int $categoryId, string $sort = 'best_selling', ?int $limit = 10): StructuredResponse
    {
        $category = Category::find($categoryId);

        if (! $category) {
            return StructuredResponse::fromText("Category with ID {$categoryId} not found.");
        }

        $limit = min($limit, 50);

        $query = Product::query()
            ->where('category_id', $categoryId)
            ->with('category');

        $query = match ($sort) {
            'top_rated' => $query->orderBy('positive_feedback', 'desc'),
            'price_low' => $query->orderBy('price', 'asc'),
            'price_high' => $query->orderBy('price', 'desc'),
            'most_viewed' => $query->orderBy('clicks', 'desc'),
            default => $query->orderBy('sales_180day', 'desc'),
        };

        $products = $query->limit($limit)->get();

        if ($products->isEmpty()) {
            return StructuredResponse::fromText("No products found in category: {$category->name_en}.");
        }

        $text = "**Products in {$category->name_en}** ({$products->count()} products, sorted by ".str_replace('_', ' ', $sort)."):\n\n";

        foreach ($products as $product) {
            $text .= "- **{$product->name_en}** (ID: {$product->id})\n";
            $text .= '  - Price: $'.number_format((float) $product->price, 2);

            if ($product->discount > 0) {
                $text .= " ({$product->discount}% off)";
            }

            $text .= " | Rating: {$product->positive_feedback}%\n";
            $text .= "  - Sales: {$product->sales_180day} in 180 days\n\n";
        }

        $html = $this->renderer->productGrid($products, "{$category->name_en} Products");

        return StructuredResponse::withHtml($text, $html, [
            'category_id' => $categoryId,
            'category_name' => $category->name_en,
            'sort' => $sort,
        ]);
    }
}
