<?php

declare(strict_types=1);

namespace Database\Seeders;

use App\Models\BasicBasketProduct;
use App\Models\Store;
use App\Models\StoreProductTarget;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use RuntimeException;

class StoreProductTargetSeeder extends Seeder
{
    use WithoutModelEvents;

    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        $products = BasicBasketProduct::query()->get()->keyBy('slug');
        $stores = Store::query()->get()->keyBy('slug');
        $storeProfiles = $this->storeProfiles();
        $targetOverrides = $this->targetOverrides();
        $rows = [];
        $now = now();

        foreach ($this->productProfiles() as $productSlug => $productProfile) {
            $product = $products->get($productSlug);

            if ($product === null) {
                throw new RuntimeException("No existe el producto base con slug [{$productSlug}] requerido por StoreProductTargetSeeder.");
            }

            foreach ($storeProfiles as $storeSlug => $storeProfile) {
                $store = $stores->get($storeSlug);

                if ($store === null) {
                    throw new RuntimeException("No existe la tienda con slug [{$storeSlug}] requerida por StoreProductTargetSeeder.");
                }

                $overrideKey = $productSlug.'@'.$storeSlug;
                $override = $targetOverrides[$overrideKey] ?? [];
                $expectedUrlContains = array_values(array_unique(array_filter(array_merge(
                    [$storeProfile['expected_domain']],
                    $productProfile['url_fragments'] ?? [],
                    $override['expected_url_contains'] ?? [],
                ))));

                $rows[] = [
                    'basic_basket_product_id' => $product->id,
                    'store_id' => $store->id,
                    'slug' => $override['slug'] ?? $productSlug.'-'.$storeSlug,
                    'name' => $override['name'] ?? $product->name.' - '.$store->name,
                    'provider' => 'dataforseo_merchant_google_products',
                    'search_query' => $override['search_query'] ?? trim($storeProfile['query_prefix'].' '.$productProfile['search_phrase']),
                    'expected_url' => $override['expected_url'] ?? null,
                    'store_product_url' => $override['store_product_url'] ?? null,
                    'expected_url_contains' => $expectedUrlContains,
                    'expected_title' => $override['expected_title'] ?? $product->name,
                    'expected_seller' => $override['expected_seller'] ?? $store->name,
                    'expected_domain' => $override['expected_domain'] ?? $storeProfile['expected_domain'],
                    'expected_position' => $override['expected_position'] ?? null,
                    'expected_rank_group' => $override['expected_rank_group'] ?? null,
                    'expected_data_docid' => $override['expected_data_docid'] ?? null,
                    'expected_product_id' => $override['expected_product_id'] ?? null,
                    'expected_gid' => $override['expected_gid'] ?? null,
                    'expected_shopping_url_contains' => $override['expected_shopping_url_contains'] ?? null,
                    'required_keywords' => $override['required_keywords'] ?? $productProfile['required_keywords'],
                    'optional_keywords' => $override['optional_keywords'] ?? $productProfile['optional_keywords'],
                    'negative_keywords' => $override['negative_keywords'] ?? $productProfile['negative_keywords'],
                    'selection_strategy' => $override['selection_strategy'] ?? 'url_weighted_match',
                    'min_match_score' => $override['min_match_score'] ?? 80,
                    'location_name' => $override['location_name'] ?? null,
                    'language_code' => $override['language_code'] ?? null,
                    'is_active' => $override['is_active'] ?? true,
                    'created_at' => $now,
                    'updated_at' => $now,
                ];
            }
        }

        // JSON-encode all array/nullable-JSON columns before bulk upsert.
        $jsonColumns = [
            'expected_url_contains',
            'expected_shopping_url_contains',
            'required_keywords',
            'optional_keywords',
            'negative_keywords',
        ];

        $rows = array_map(static function (array $row) use ($jsonColumns): array {
            foreach ($jsonColumns as $jsonColumn) {
                if ($row[$jsonColumn] === null) {
                    continue;
                }
                $row[$jsonColumn] = json_encode($row[$jsonColumn], JSON_THROW_ON_ERROR);
            }

            return $row;
        }, $rows);

        StoreProductTarget::query()->upsert(
            $rows,
            ['slug'],
            [
                'basic_basket_product_id',
                'store_id',
                'name',
                'provider',
                'search_query',
                'expected_url',
                'store_product_url',
                'expected_url_contains',
                'expected_title',
                'expected_seller',
                'expected_domain',
                'expected_position',
                'expected_rank_group',
                'expected_data_docid',
                'expected_product_id',
                'expected_gid',
                'expected_shopping_url_contains',
                'required_keywords',
                'optional_keywords',
                'negative_keywords',
                'selection_strategy',
                'min_match_score',
                'location_name',
                'language_code',
                'is_active',
                'updated_at',
            ],
        );
    }

    /**
     * Fragmentos de URL en productProfiles: solo poner términos GENÉRICOS que sirvan para TODAS las tiendas.
     * Ejemplo correcto:  'url_fragments' => ['tortilla-de-maiz']         ← aparece en la ruta de cualquier tienda
     * Ejemplo incorrecto: 'url_fragments' => ['/p/00020045100000']        ← SKU específico de Chedraui
     * Para fragmentos específicos por tienda usa targetOverrides() con la clave 'producto@tienda'.
     *
     * @return array<string, array<string, mixed>>
     */
    private function productProfiles(): array
    {
        return [
            'tortilla-maiz-kilo' => ['search_phrase' => 'tortillas de maiz 1 kg', 'required_keywords' => ['tortilla', 'maiz', 'kilo'], 'optional_keywords' => ['masa'], 'negative_keywords' => ['harina', 'tostadas', 'totopos', 'tortillinas', 'paquete'], 'url_fragments' => ['tortilla-de-maiz']],
            'leche-entera-1l' => ['search_phrase' => 'leche entera 1 litro', 'required_keywords' => ['leche', 'entera', '1', 'litro'], 'optional_keywords' => ['ultra', 'pasteurizada'], 'negative_keywords' => ['deslactosada', 'light', 'almendra', 'soya'], 'url_fragments' => ['leche', 'entera']],
            'huevo-blanco-18-pzas' => ['search_phrase' => 'huevo blanco 18 piezas', 'required_keywords' => ['huevo', 'blanco', '18'], 'optional_keywords' => ['piezas', 'paquete'], 'negative_keywords' => ['codorniz', 'organico', '30'], 'url_fragments' => ['huevo', '18']],
            'arroz-1kg' => ['search_phrase' => 'arroz 1 kg', 'required_keywords' => ['arroz', '1', 'kg'], 'optional_keywords' => ['blanco'], 'negative_keywords' => ['integral', 'precocido', '2', '5kg'], 'url_fragments' => ['arroz']],
            'frijol-negro-1kg' => ['search_phrase' => 'frijol negro 1 kg', 'required_keywords' => ['frijol', 'negro', '1', 'kg'], 'optional_keywords' => ['grano'], 'negative_keywords' => ['bayo', 'pinto', 'refrito'], 'url_fragments' => ['frijol', 'negro']],
            'azucar-blanca-1kg' => ['search_phrase' => 'azucar blanca 1 kg', 'required_keywords' => ['azucar', 'blanca', '1', 'kg'], 'optional_keywords' => ['refinada'], 'negative_keywords' => ['morena', 'glass', 'splenda'], 'url_fragments' => ['azucar']],
            'aceite-vegetal-850ml' => ['search_phrase' => 'aceite vegetal 850 ml', 'required_keywords' => ['aceite', 'vegetal', '850'], 'optional_keywords' => ['comestible'], 'negative_keywords' => ['oliva', 'spray', 'aerosol'], 'url_fragments' => ['aceite', 'vegetal']],
            'atun-en-agua-140g' => ['search_phrase' => 'atun en agua 140 g', 'required_keywords' => ['atun', 'agua', '140'], 'optional_keywords' => ['lata'], 'negative_keywords' => ['pouch', 'aceite', 'ensalada'], 'url_fragments' => ['atun']],
            'papel-higienico-4-rollos' => ['search_phrase' => 'papel higienico 4 rollos', 'required_keywords' => ['papel', 'higienico', '4', 'rollos'], 'optional_keywords' => ['rollo'], 'negative_keywords' => ['12', '24', 'servilletas'], 'url_fragments' => ['papel', 'higienico']],
            'pan-blanco-bolsa-680g' => ['search_phrase' => 'pan blanco de caja 680 g', 'required_keywords' => ['pan', 'blanco', '680'], 'optional_keywords' => ['caja'], 'negative_keywords' => ['integral', 'multigrano', 'hamburguesa'], 'url_fragments' => ['pan', 'blanco']],
            'pasta-spaghetti-200g' => ['search_phrase' => 'spaghetti 200 g', 'required_keywords' => ['spaghetti', '200'], 'optional_keywords' => ['pasta'], 'negative_keywords' => ['fusilli', 'codito', 'integral'], 'url_fragments' => ['spaghetti', 'pasta']],
            'harina-de-trigo-1kg' => ['search_phrase' => 'harina de trigo 1 kg', 'required_keywords' => ['harina', 'trigo', '1', 'kg'], 'optional_keywords' => ['todo', 'uso'], 'negative_keywords' => ['hot cakes', 'premezcla', 'maiz'], 'url_fragments' => ['harina', 'trigo']],
            'harina-de-maiz-1kg' => ['search_phrase' => 'harina de maiz 1 kg', 'required_keywords' => ['harina', 'maiz', '1', 'kg'], 'optional_keywords' => ['masa'], 'negative_keywords' => ['trigo', 'avena', 'preparada'], 'url_fragments' => ['harina', 'maiz']],
            'sal-de-mesa-1kg' => ['search_phrase' => 'sal de mesa 1 kg', 'required_keywords' => ['sal', 'mesa', '1', 'kg'], 'optional_keywords' => ['yodada'], 'negative_keywords' => ['marina', 'baja en sodio'], 'url_fragments' => ['sal']],
            'cafe-soluble-100g' => ['search_phrase' => 'cafe soluble 100 g', 'required_keywords' => ['cafe', 'soluble', '100'], 'optional_keywords' => ['frasco'], 'negative_keywords' => ['capsulas', 'grano', 'descafeinado'], 'url_fragments' => ['cafe', 'soluble']],
            'avena-hojuelas-400g' => ['search_phrase' => 'avena en hojuelas 400 g', 'required_keywords' => ['avena', 'hojuelas', '400'], 'optional_keywords' => ['cereal'], 'negative_keywords' => ['granola', 'instantanea'], 'url_fragments' => ['avena']],
            'lenteja-500g' => ['search_phrase' => 'lenteja 500 g', 'required_keywords' => ['lenteja', '500'], 'optional_keywords' => ['grano'], 'negative_keywords' => ['sopa', 'mezcla'], 'url_fragments' => ['lenteja']],
            'sardina-en-tomate-425g' => ['search_phrase' => 'sardina en tomate 425 g', 'required_keywords' => ['sardina', 'tomate', '425'], 'optional_keywords' => ['lata'], 'negative_keywords' => ['atun', 'aceite'], 'url_fragments' => ['sardina']],
            'pure-de-tomate-210g' => ['search_phrase' => 'pure de tomate 210 g', 'required_keywords' => ['pure', 'tomate', '210'], 'optional_keywords' => ['envase'], 'negative_keywords' => ['catsup', 'salsa'], 'url_fragments' => ['tomate', 'pure']],
            'galletas-saladas-200g' => ['search_phrase' => 'galletas saladas 200 g', 'required_keywords' => ['galletas', 'saladas', '200'], 'optional_keywords' => ['crackers'], 'negative_keywords' => ['dulces', 'chocolate'], 'url_fragments' => ['galletas', 'saladas']],
            'jabon-de-bano-barra-150g' => ['search_phrase' => 'jabon de bano en barra 150 g', 'required_keywords' => ['jabon', 'barra', '150'], 'optional_keywords' => ['bano'], 'negative_keywords' => ['liquido', 'antibacterial', 'paquete'], 'url_fragments' => ['jabon']],
            'jabon-para-ropa-barra-400g' => ['search_phrase' => 'jabon para ropa en barra 400 g', 'required_keywords' => ['jabon', 'ropa', 'barra', '400'], 'optional_keywords' => ['lavar'], 'negative_keywords' => ['liquido', 'suavizante'], 'url_fragments' => ['jabon', 'ropa']],
            'detergente-para-ropa-1kg' => ['search_phrase' => 'detergente para ropa 1 kg', 'required_keywords' => ['detergente', 'ropa', '1', 'kg'], 'optional_keywords' => ['polvo'], 'negative_keywords' => ['liquido', 'suavizante', 'lavatrastes'], 'url_fragments' => ['detergente']],
            'shampoo-750ml' => ['search_phrase' => 'shampoo 750 ml', 'required_keywords' => ['shampoo', '750'], 'optional_keywords' => ['cabello'], 'negative_keywords' => ['acondicionador', 'mini', 'sobres'], 'url_fragments' => ['shampoo']],
        ];
    }

    /**
     * Edita este arreglo para agregar nuevas tiendas o ajustar comportamiento de búsqueda por tienda.
     *
     * @return array<string, array<string, mixed>>
     */
    private function storeProfiles(): array
    {
        return [
            'bodega-aurrera' => ['query_prefix' => 'bodega aurrera', 'expected_domain' => 'bodegaaurrera.com.mx'],
            'soriana' => ['query_prefix' => 'soriana', 'expected_domain' => 'soriana.com.mx'],
            'chedraui' => ['query_prefix' => 'chedraui', 'expected_domain' => 'chedraui.com.mx'],
        ];
    }

    /**
     * Afina targets específicos por combinación producto@tienda.
     *
     * Campos disponibles:
     *  - expected_url                   → URL exacta del producto en la tienda para señal de matching (solo si existe directUrl real)
     *  - store_product_url              → URL real del producto en la tienda para el botón "Ir al producto" del frontend
     *  - expected_url_contains          → fragmentos de URL (se SUMAN a los genéricos de productProfiles)
     *  - expected_shopping_url_contains → fragmentos de la URL de Google Shopping (shopping_url)
     *  - expected_title                 → título exacto o cercano del producto en esa tienda
     *  - expected_seller                → nombre del seller como aparece en DataForSEO
     *  - expected_domain                → dominio esperado de la tienda
     *  - expected_position              → rank_absolute esperado
     *  - expected_rank_group            → rank_group esperado
     *  - expected_data_docid            → data_docid de Google Shopping (señal de matching fuerte)
     *  - expected_product_id            → product_id si está disponible
     *  - expected_gid                   → gid si está disponible
     *  - required_keywords              → sobreescribe los del productProfile
     *  - optional_keywords              → sobreescribe los del productProfile
     *  - negative_keywords              → sobreescribe los del productProfile
     *  - min_match_score                → umbral mínimo de score para considerar match
     *  - selection_strategy             → estrategia de selección de resultados
     *  - search_query                   → query de búsqueda diferente a la genérica
     *  - location_name                  → nombre de ubicación para búsqueda localizada
     *  - language_code                  → código de idioma (ej: 'es')
     *  - is_active                      → si el target está activo
     *
     * Llave: product_slug@store_slug
     * Los fragmentos de 'expected_url_contains' se SUMAN a los genéricos de productProfiles y al dominio de la tienda.
     *
     * @return array<string, array<string, mixed>>
     */
    private function targetOverrides(): array
    {
        return [
            // ── Tortilla de maíz ────────────────────────────────────────────────
            //
            // Bodega Aurrera: url y domain vienen null en Merchant API;
            // se identifican por seller + title + keywords + ranking + docid.
            'tortilla-maiz-kilo@bodega-aurrera' => [
                'search_query' => 'tortillas de maiz 1 kg',
                'expected_seller' => 'Bodega Aurrera Despensa a tu Casa',
                'expected_title' => 'Tortilla de maíz por kilo',
                'expected_data_docid' => '1712851062477582571',
                'expected_shopping_url_contains' => [
                    'headlineOfferDocid:1712851062477582571',
                ],
                'store_product_url' => 'https://despensa.bodegaaurrera.com.mx/ip/tortilla-de-maiz-por-kilo/00000000000451',
            ],
            'tortilla-maiz-kilo@soriana' => [
                'search_query' => 'tortillas de maiz 1 kg',
                'expected_seller' => 'Soriana.com',
                'expected_title' => 'Tortilla De Maíz Blanca 1 Kg',
                'expected_position' => 1,
                'expected_rank_group' => 1,
                'expected_data_docid' => '11264669339232586754',
                'expected_product_id' => '7550984573579189655',
                'expected_shopping_url_contains' => [
                    'headlineOfferDocid:11264669339232586754',
                ],
                'store_product_url' => 'https://www.soriana.com/tortilla-de-maiz-blanca-1-kg/11557167.html',
            ],
            'tortilla-maiz-kilo@chedraui' => [
                'search_query' => 'chedraui tortillas de maiz 1 kg',
                'expected_seller' => 'Chedraui',
                'expected_title' => 'Tortilla de Maíz Amarillo Kg',
                'expected_position' => 1,
                'expected_rank_group' => 1,
                'expected_data_docid' => '8953249476411266307',
                // 'expected_product_id' => '00020045100000',
                'expected_shopping_url_contains' => [
                    'headlineOfferDocid:8953249476411266307',
                ],
                'store_product_url' => 'https://www.chedraui.com.mx/tortilla-de-maiz-amarillo-kg-3108088/p?ta=1779803749&srsltid=AfmBOoq32EzgHqPY-e4OGB6OladnaIW5KzasLsssurWHVA19hsd-kbAfnBI',
            ],
            // Una vez que confirmes las URLs reales en cada tienda, descomenta y ajusta:
            // 'tortilla-maiz-kilo@soriana' => [
            //     'search_query' => 'soriana tortillas de maiz 1 kg',
            //     'expected_title' => 'Tortilla de Maíz 1 kg',
            // ],
        ];
    }
}
