<?php

declare(strict_types=1);

namespace Database\Seeders;

use App\Enums\PriceSyncRunStatus;
use App\Enums\PriceSyncTaskStatus;
use App\Models\BasicBasketProduct;
use App\Models\PriceObservation;
use App\Models\PriceSyncRun;
use App\Models\PriceSyncTask;
use App\Models\Store;
use App\Models\StoreProductTarget;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;

/**
 * Puebla la base de datos con datos de demostración para probar la API pública de canasta básica.
 *
 * Escenarios cubiertos:
 *  - Producto con precio fresco en 3 tiendas            → is_price_stale = false
 *  - Producto con precio de ayer en 1 tienda            → is_price_stale = true (fallback histórico)
 *  - Producto con targets pero sin observaciones        → price = null
 *  - Producto con store_product_url configurado         → external_url = URL real
 *  - Producto con store_product_url = null              → external_url = null
 *  - Productos de distintas categorías para filtros
 *
 * IMPORTANTE: Solo crea registros con el prefijo "demo-" en los slugs.
 * Es idempotente: elimina y recrea observaciones en cada ejecución.
 *
 * Uso:
 *   php artisan db:seed --class=BasicBasketDemoSeeder
 */
class BasicBasketDemoSeeder extends Seeder
{
    use WithoutModelEvents;

    public function run(): void
    {
        [$bodega, $soriana, $chedraui] = $this->upsertStores();

        [
            $tortilla,
            $leche,
            $arroz,
            $huevo,
            $azucar,
        ] = $this->upsertProducts();

        $targets = $this->upsertTargets($tortilla, $leche, $arroz, $huevo, $azucar, $bodega, $soriana, $chedraui);

        $this->recreateObservations($targets, $bodega, $soriana, $chedraui, $tortilla, $leche, $arroz, $azucar);

        $this->command->info('✅ BasicBasketDemoSeeder ejecutado. '.count($targets).' targets, observaciones recreadas.');
    }

    // ──────────────────────────────────────────────────────────────────────────
    // Stores
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * @return array<int, Store>
     */
    private function upsertStores(): array
    {
        $stores = [
            [
                'slug' => 'demo-bodega-aurrera',
                'name' => 'Bodega Aurrera (Demo)',
                'domains' => json_encode(['demo-bodegaaurrera.com.mx']),
                'aliases' => json_encode(['Demo Bodega Aurrera']),
                'is_active' => true,
                'logo_url' => '/images/tiendas/bodega-aurrera.png',
            ],
            [
                'slug' => 'demo-soriana',
                'name' => 'Soriana (Demo)',
                'domains' => json_encode(['demo-soriana.com.mx']),
                'aliases' => json_encode(['Demo Soriana']),
                'is_active' => true,
                'logo_url' => '/images/tiendas/soriana.jpg',
            ],
            [
                'slug' => 'demo-chedraui',
                'name' => 'Chedraui (Demo)',
                'domains' => json_encode(['demo-chedraui.com.mx']),
                'aliases' => json_encode(['Demo Chedraui']),
                'is_active' => true,
                'logo_url' => '/images/tiendas/chedraui.png',
            ],
        ];

        Store::query()->upsert($stores, ['slug'], ['name', 'domains', 'aliases', 'is_active', 'logo_url']);

        return Store::query()->whereIn('slug', array_column($stores, 'slug'))->orderBy('slug')->get()->all();
    }

    // ──────────────────────────────────────────────────────────────────────────
    // Products
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * @return array<int, BasicBasketProduct>
     */
    private function upsertProducts(): array
    {
        $now = now();

        $products = [
            // 1. Precios frescos en 3 tiendas — is_price_stale = false
            ['slug' => 'demo-tortilla-maiz-kilo', 'name' => 'Tortilla de maíz por kilo (Demo)', 'category' => 'Tortillas', 'expected_unit' => 'kg', 'description' => 'Demo: tortilla de maíz.', 'image_url' => '/images/productos/23_tortilla-de-maiz.jpg', 'is_active' => true, 'created_at' => $now, 'updated_at' => $now],
            // 2. Precio fresco en 2 tiendas, stale en 1 — is_price_stale true/false mixto
            ['slug' => 'demo-leche-entera-1l', 'name' => 'Leche entera 1 litro (Demo)', 'category' => 'Lácteos', 'expected_unit' => 'l', 'description' => 'Demo: leche entera.', 'image_url' => '/images/productos/13_leche-de-vaca.jpg', 'is_active' => true, 'created_at' => $now, 'updated_at' => $now],
            // 3. Solo 1 tienda con precio stale (hace 5 días), las otras sin observación
            ['slug' => 'demo-arroz-1kg', 'name' => 'Arroz 1 kg (Demo)', 'category' => 'Granos', 'expected_unit' => 'kg', 'description' => 'Demo: arroz blanco.', 'image_url' => '/images/productos/02_arroz-en-grano.jpg', 'is_active' => true, 'created_at' => $now, 'updated_at' => $now],
            // 4. Targets sin observaciones — price = null en todas las tiendas
            ['slug' => 'demo-huevo-blanco-18-pzas', 'name' => 'Huevo blanco 18 piezas (Demo)', 'category' => 'Huevos', 'expected_unit' => 'paquete', 'description' => 'Demo: sin precios aún.', 'image_url' => '/images/productos/10_huevo-de-gallina.jpg', 'is_active' => true, 'created_at' => $now, 'updated_at' => $now],
            // 5. Precios frescos + store_product_url configurado → external_url disponible
            ['slug' => 'demo-azucar-blanca-1kg', 'name' => 'Azúcar blanca 1 kg (Demo)', 'category' => 'Abarrotes', 'expected_unit' => 'kg', 'description' => 'Demo: azúcar blanca con URL de producto.', 'image_url' => '/images/productos/04_azucar-estandar.jpg', 'is_active' => true, 'created_at' => $now, 'updated_at' => $now],
        ];

        BasicBasketProduct::query()->upsert(
            $products,
            ['slug'],
            ['name', 'category', 'expected_unit', 'description', 'image_url', 'is_active', 'updated_at'],
        );

        return BasicBasketProduct::query()
            ->whereIn('slug', array_column($products, 'slug'))
            ->orderBy('slug')
            ->get()
            ->all();
    }

    // ──────────────────────────────────────────────────────────────────────────
    // Targets
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * @return array<string, StoreProductTarget> Keyed as "product_slug@store_slug"
     */
    private function upsertTargets(
        BasicBasketProduct $tortilla,
        BasicBasketProduct $leche,
        BasicBasketProduct $arroz,
        BasicBasketProduct $huevo,
        BasicBasketProduct $azucar,
        Store $bodega,
        Store $soriana,
        Store $chedraui,
    ): array {
        $now = now();

        /**
         * @var array<string, array{product: BasicBasketProduct, store: Store, store_product_url: string|null}> $matrix
         */
        $matrix = [
            'demo-tortilla-maiz-kilo@demo-bodega-aurrera' => ['product' => $tortilla, 'store' => $bodega, 'store_product_url' => 'https://demo-bodegaaurrera.com.mx/tortilla-1kg'],
            'demo-tortilla-maiz-kilo@demo-soriana' => ['product' => $tortilla, 'store' => $soriana, 'store_product_url' => null],
            'demo-tortilla-maiz-kilo@demo-chedraui' => ['product' => $tortilla, 'store' => $chedraui, 'store_product_url' => null],

            'demo-leche-entera-1l@demo-bodega-aurrera' => ['product' => $leche, 'store' => $bodega, 'store_product_url' => null],
            'demo-leche-entera-1l@demo-soriana' => ['product' => $leche, 'store' => $soriana, 'store_product_url' => null],
            'demo-leche-entera-1l@demo-chedraui' => ['product' => $leche, 'store' => $chedraui, 'store_product_url' => null],

            'demo-arroz-1kg@demo-bodega-aurrera' => ['product' => $arroz, 'store' => $bodega, 'store_product_url' => null],
            'demo-arroz-1kg@demo-soriana' => ['product' => $arroz, 'store' => $soriana, 'store_product_url' => null],
            'demo-arroz-1kg@demo-chedraui' => ['product' => $arroz, 'store' => $chedraui, 'store_product_url' => null],

            'demo-huevo-blanco-18-pzas@demo-bodega-aurrera' => ['product' => $huevo, 'store' => $bodega, 'store_product_url' => null],
            'demo-huevo-blanco-18-pzas@demo-soriana' => ['product' => $huevo, 'store' => $soriana, 'store_product_url' => null],
            'demo-huevo-blanco-18-pzas@demo-chedraui' => ['product' => $huevo, 'store' => $chedraui, 'store_product_url' => null],

            'demo-azucar-blanca-1kg@demo-bodega-aurrera' => ['product' => $azucar, 'store' => $bodega, 'store_product_url' => 'https://demo-bodegaaurrera.com.mx/azucar-1kg'],
            'demo-azucar-blanca-1kg@demo-soriana' => ['product' => $azucar, 'store' => $soriana, 'store_product_url' => 'https://demo-soriana.com.mx/azucar-1kg'],
            'demo-azucar-blanca-1kg@demo-chedraui' => ['product' => $azucar, 'store' => $chedraui, 'store_product_url' => 'https://demo-chedraui.com.mx/azucar-1kg'],
        ];

        $rows = [];

        foreach ($matrix as $key => $entry) {
            $rows[] = [
                'basic_basket_product_id' => $entry['product']->id,
                'store_id' => $entry['store']->id,
                'slug' => $key,
                'name' => $entry['product']->name.' - '.$entry['store']->name,
                'provider' => 'dataforseo_merchant_google_products',
                'search_query' => $entry['product']->name.' '.$entry['store']->name,
                'expected_url' => null,
                'store_product_url' => $entry['store_product_url'],
                'expected_url_contains' => json_encode([]),
                'expected_title' => $entry['product']->name,
                'expected_seller' => $entry['store']->name,
                'expected_domain' => $entry['store']->slug.'.com.mx',
                'expected_position' => null,
                'expected_rank_group' => null,
                'expected_data_docid' => null,
                'expected_product_id' => null,
                'expected_gid' => null,
                'expected_shopping_url_contains' => null,
                'required_keywords' => json_encode([]),
                'optional_keywords' => json_encode([]),
                'negative_keywords' => json_encode([]),
                'selection_strategy' => 'url_weighted_match',
                'min_match_score' => 80,
                'location_name' => 'Mexico',
                'language_code' => 'es',
                'is_active' => true,
                'created_at' => $now,
                'updated_at' => $now,
            ];
        }

        StoreProductTarget::query()->upsert($rows, ['slug'], [
            'basic_basket_product_id', 'store_id', 'name', 'store_product_url',
            'expected_title', 'expected_seller', 'expected_domain', 'is_active', 'updated_at',
        ]);

        $slugs = array_keys($matrix);

        return StoreProductTarget::query()
            ->whereIn('slug', $slugs)
            ->with('store')
            ->get()
            ->keyBy('slug')
            ->all();
    }

    // ──────────────────────────────────────────────────────────────────────────
    // Price Observations
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Elimina y recrea todas las observaciones de los targets demo.
     *
     * @param  array<string, StoreProductTarget>  $targets
     */
    private function recreateObservations(
        array $targets,
        Store $bodega,
        Store $soriana,
        Store $chedraui,
        BasicBasketProduct $tortilla,
        BasicBasketProduct $leche,
        BasicBasketProduct $arroz,
        BasicBasketProduct $azucar,
    ): void {
        $targetIds = array_map(static fn (StoreProductTarget $t): int => $t->id, $targets);

        // Limpia observaciones y tasks previas para obtener un estado limpio
        PriceObservation::query()->whereIn('store_product_target_id', $targetIds)->delete();
        PriceSyncTask::query()->whereIn('store_product_target_id', $targetIds)->delete();

        $run = PriceSyncRun::query()->create([
            'provider' => 'dataforseo_merchant_google_products',
            'status' => PriceSyncRunStatus::Completed,
            'started_at' => now()->subHour(),
            'finished_at' => now(),
            'total_targets' => count($targetIds),
            'tasks_submitted' => count($targetIds),
            'matched_count' => 12,
            'not_matched_count' => 3,
            'ambiguous_count' => 0,
            'empty_results_count' => 0,
            'api_error_count' => 0,
            'error_count' => 0,
            'summary' => ['mode' => 'demo'],
        ]);

        /**
         * Definición de observaciones a crear.
         * null en 'observed_at' significa "sin observación" para ese target.
         *
         * @var array<string, array{product: BasicBasketProduct, store: Store, price: string, observed_at: Carbon}|null> $observations
         */
        $observations = [
            // ── Tortilla: precios frescos de hoy en 3 tiendas ─────────────
            'demo-tortilla-maiz-kilo@demo-bodega-aurrera' => [
                'product' => $tortilla, 'store' => $bodega,
                'price' => '24.90', 'observed_at' => now(),
                'detected_title' => 'Tortilla de Maíz por Kilo', 'detected_seller' => 'Bodega Aurrera Despensa a tu Casa',
            ],
            'demo-tortilla-maiz-kilo@demo-soriana' => [
                'product' => $tortilla, 'store' => $soriana,
                'price' => '26.50', 'observed_at' => now(),
                'detected_title' => 'Tortilla De Maíz Blanca 1 Kg', 'detected_seller' => 'Soriana.com',
            ],
            'demo-tortilla-maiz-kilo@demo-chedraui' => [
                'product' => $tortilla, 'store' => $chedraui,
                'price' => '25.70', 'observed_at' => now(),
                'detected_title' => 'Tortilla de Maíz Amarillo Kg', 'detected_seller' => 'Chedraui',
            ],

            // ── Leche: Bodega y Soriana fresco hoy, Chedraui stale (3 días) ──
            'demo-leche-entera-1l@demo-bodega-aurrera' => [
                'product' => $leche, 'store' => $bodega,
                'price' => '22.00', 'observed_at' => now(),
                'detected_title' => 'Leche Entera 1L', 'detected_seller' => 'Bodega Aurrera Despensa a tu Casa',
            ],
            'demo-leche-entera-1l@demo-soriana' => [
                'product' => $leche, 'store' => $soriana,
                'price' => '23.50', 'observed_at' => now(),
                'detected_title' => 'Leche Entera 1 Litro', 'detected_seller' => 'Soriana.com',
            ],
            'demo-leche-entera-1l@demo-chedraui' => [
                'product' => $leche, 'store' => $chedraui,
                'price' => '21.80', 'observed_at' => now()->subDays(3),
                'detected_title' => 'Leche Entera Chedraui 1 l', 'detected_seller' => 'Chedraui',
            ],

            // ── Arroz: solo Soriana tiene precio, stale (5 días). Bodega y Chedraui = sin observación ──
            'demo-arroz-1kg@demo-bodega-aurrera' => null,
            'demo-arroz-1kg@demo-soriana' => [
                'product' => $arroz, 'store' => $soriana,
                'price' => '18.50', 'observed_at' => now()->subDays(5),
                'detected_title' => 'Arroz Blanco 1 kg', 'detected_seller' => 'Soriana.com',
            ],
            'demo-arroz-1kg@demo-chedraui' => null,

            // ── Huevo: sin observaciones en ninguna tienda ─────────────────
            'demo-huevo-blanco-18-pzas@demo-bodega-aurrera' => null,
            'demo-huevo-blanco-18-pzas@demo-soriana' => null,
            'demo-huevo-blanco-18-pzas@demo-chedraui' => null,

            // ── Azúcar: precios frescos + store_product_url en todas ───────
            'demo-azucar-blanca-1kg@demo-bodega-aurrera' => [
                'product' => $azucar, 'store' => $bodega,
                'price' => '28.00', 'observed_at' => now(),
                'detected_title' => 'Azúcar Estándar 1 kg', 'detected_seller' => 'Bodega Aurrera Despensa a tu Casa',
            ],
            'demo-azucar-blanca-1kg@demo-soriana' => [
                'product' => $azucar, 'store' => $soriana,
                'price' => '29.50', 'observed_at' => now(),
                'detected_title' => 'Azúcar Blanca Refinada 1 kg', 'detected_seller' => 'Soriana.com',
            ],
            'demo-azucar-blanca-1kg@demo-chedraui' => [
                'product' => $azucar, 'store' => $chedraui,
                'price' => '27.80', 'observed_at' => now(),
                'detected_title' => 'Azúcar Blanca 1 Kg', 'detected_seller' => 'Chedraui',
            ],
        ];

        foreach ($observations as $targetSlug => $obs) {
            if ($obs === null) {
                continue;
            }

            /** @var StoreProductTarget $target */
            $target = $targets[$targetSlug];

            $task = PriceSyncTask::query()->create([
                'price_sync_run_id' => $run->id,
                'store_product_target_id' => $target->id,
                'provider' => 'dataforseo_merchant_google_products',
                'provider_task_id' => 'demo-task-'.$target->slug,
                'query' => $target->search_query,
                'location_name' => 'Mexico',
                'language_code' => 'es',
                'endpoint' => '/v3/merchant/google/products/task_post',
                'status' => PriceSyncTaskStatus::Completed,
                'attempts' => 1,
                'submitted_at' => $obs['observed_at']->copy()->subMinutes(30),
                'completed_at' => $obs['observed_at'],
                'error_message' => null,
                'request_payload' => ['keyword' => $target->search_query],
                'raw_response' => null,
            ]);

            PriceObservation::query()->create([
                'price_sync_task_id' => $task->id,
                'store_product_target_id' => $target->id,
                'basic_basket_product_id' => $obs['product']->id,
                'store_id' => $obs['store']->id,
                'provider' => 'dataforseo_merchant_google_products',
                'query' => $target->search_query,
                'detected_title' => $obs['detected_title'],
                'detected_seller' => $obs['detected_seller'],
                'detected_domain' => $obs['store']->slug.'.com.mx',
                'original_url' => 'https://demo-'.$obs['store']->slug.'.com.mx/producto/demo',
                'normalized_url' => 'https://demo-'.$obs['store']->slug.'.com.mx/producto/demo',
                'price' => $obs['price'],
                'currency' => 'MXN',
                'match_score' => 95,
                'selection_strategy' => 'url_weighted_match',
                'observed_at' => $obs['observed_at'],
            ]);
        }
    }
}
