<?php

namespace Modules\Bms\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Modules\Bms\Entities\BmsAddon;
use Modules\Bms\Entities\BmsArea;
use Modules\Bms\Entities\BmsAsset;
use Modules\Bms\Entities\BmsHall;
use Modules\Bms\Entities\BmsHallMedia;
use Modules\Bms\Entities\BmsMatchingSetting;
use Modules\Bms\Entities\BmsPackage;
use Modules\Bms\Entities\BmsPackageItem;
use Modules\Bms\Entities\BmsVenue;
use Modules\Bms\Services\Contracts\AssetServiceContract;

/**
 * Seeds a realistic demo set (areas → venues → halls → packages → add-ons →
 * matching settings) for the first business so P1 and the matching engine are
 * demoable immediately. Idempotent: re-running won't duplicate rows.
 */
class BmsDemoSeeder extends Seeder
{
    /** Verified real wedding photos (Unsplash, free licence). */
    private const WEDDING_PHOTOS = [
        '1519225421980-715cb0215aed', // long wedding table + florals
        '1464366400600-7168b8af9bc3', // banquet reception hall
        '1465495976277-4387d4b0b4c6', // wedding rings on hands
        '1511795409834-ef04bbd61622', // elegant place setting
        '1519671482749-fd09be7ccebf', // toast / celebration
        '1606216794074-735e91aa2c92', // bride & groom
        '1507504031003-b417219a0fde', // "Mr & Mrs" sign
    ];

    /** Real wedding-tour video (Wikimedia, CC-BY) — Gulf/Arab wedding procession. */
    /** Real Askar Group wedding videos (YouTube) — rendered as embeds in the funnel. */
    private const ASKAR_VIDEOS = [
        'https://youtu.be/pWR5rSnBeRQ',
        'https://youtu.be/6HF2JyEiB40',
        'https://youtu.be/MhEDYpy0FLQ',
        'https://youtube.com/shorts/HKh2IfmWdbw',
    ];
    private const WEDDING_VIDEO = 'https://youtu.be/pWR5rSnBeRQ';

    /**
     * Elegant grand-hall 360° (Poly Haven, CC0) hosted locally so Pannellum
     * loads it same-origin (no CORS). Root-relative so it works on http/https.
     * Swap for the hall's own 360 from the back-office Media manager at go-live.
     */
    private const VENUE_360 = '/static-purchase/public/bms-assets/venue-360.jpg';

    public function run(): void
    {
        $businessId = (int) (DB::table('business')->min('id') ?? 0);
        if ($businessId === 0) {
            $this->command?->warn('[BMS] No business found — skipping demo seed.');
            return;
        }

        $locationId = DB::table('business_locations')
            ->where('business_id', $businessId)
            ->value('id');

        $this->command?->info("[BMS] Seeding demo data for business #{$businessId} (location #" . ($locationId ?? 'none') . ')');

        // ---- Areas -------------------------------------------------------
        $newCairo = BmsArea::firstOrCreate(
            ['business_id' => $businessId, 'name' => 'New Cairo'],
            ['name_ar' => 'القاهرة الجديدة', 'location_id' => $locationId, 'is_active' => true, 'sort_order' => 1]
        );
        $sheikhZayed = BmsArea::firstOrCreate(
            ['business_id' => $businessId, 'name' => 'Sheikh Zayed'],
            ['name_ar' => 'الشيخ زايد', 'location_id' => $locationId, 'is_active' => true, 'sort_order' => 2]
        );

        // ---- Venues ------------------------------------------------------
        $grand = BmsVenue::firstOrCreate(
            ['business_id' => $businessId, 'name' => 'International Grand — New Cairo'],
            [
                'name_ar' => 'إنترناشيونال جراند — القاهرة الجديدة',
                'location_id' => $locationId, 'area_id' => $newCairo->id,
                'city' => 'Cairo', 'is_active' => true, 'sort_order' => 1,
            ]
        );
        $riverside = BmsVenue::firstOrCreate(
            ['business_id' => $businessId, 'name' => 'International Riverside — Giza'],
            [
                'name_ar' => 'إنترناشيونال ريفرسايد — الجيزة',
                'location_id' => $locationId, 'area_id' => $sheikhZayed->id,
                'city' => 'Giza', 'is_active' => true, 'sort_order' => 2,
            ]
        );

        // ---- Halls -------------------------------------------------------
        $halls = [
            [
                'venue' => $grand, 'area' => $newCairo,
                'name' => 'Royal Grand Ballroom', 'name_ar' => 'قاعة رويال جراند',
                'capacity_min' => 200, 'capacity_max' => 600, 'venue_type' => 'closed',
                'fnb_levels' => ['set_menu', 'open_buffet', 'custom'],
                'min_budget' => 150000, 'base_price' => 120000,
                'features' => ['stage' => true, 'bridal_room' => true, 'valet' => true, 'led_screens' => true],
            ],
            [
                'venue' => $grand, 'area' => $newCairo,
                'name' => 'Crystal Hall', 'name_ar' => 'قاعة كريستال',
                'capacity_min' => 150, 'capacity_max' => 400, 'venue_type' => 'both',
                'fnb_levels' => ['set_menu', 'open_buffet'],
                'min_budget' => 110000, 'base_price' => 90000,
                'features' => ['stage' => true, 'bridal_room' => true, 'parking' => true],
            ],
            [
                'venue' => $grand, 'area' => $newCairo,
                'name' => 'Emerald Hall', 'name_ar' => 'قاعة إميرالد',
                'capacity_min' => 300, 'capacity_max' => 800, 'venue_type' => 'closed',
                'fnb_levels' => ['open_buffet', 'custom'],
                'min_budget' => 220000, 'base_price' => 180000,
                'features' => ['stage' => true, 'bridal_room' => true, 'valet' => true, 'led_screens' => true],
            ],
            [
                'venue' => $riverside, 'area' => $sheikhZayed,
                'name' => 'Nile Terrace (Open-air)', 'name_ar' => 'تراس النيل (هواء طلق)',
                'capacity_min' => 100, 'capacity_max' => 300, 'venue_type' => 'open',
                'fnb_levels' => ['high_tea', 'drinks_only', 'set_menu'],
                'min_budget' => 90000, 'base_price' => 70000,
                'features' => ['river_view' => true, 'valet' => true],
            ],
            [
                'venue' => $riverside, 'area' => $sheikhZayed,
                'name' => 'Garden Pavilion', 'name_ar' => 'جناح الحديقة',
                'capacity_min' => 50, 'capacity_max' => 150, 'venue_type' => 'open',
                'fnb_levels' => ['high_tea', 'drinks_only'],
                'min_budget' => 40000, 'base_price' => 30000,
                'features' => ['garden' => true, 'parking' => true],
            ],
        ];

        $createdHalls = [];
        foreach ($halls as $i => $h) {
            $hall = BmsHall::firstOrCreate(
                ['business_id' => $businessId, 'venue_id' => $h['venue']->id, 'name' => $h['name']],
                [
                    'name_ar' => $h['name_ar'],
                    'location_id' => $locationId,
                    'area_id' => $h['area']->id,
                    'capacity_min' => $h['capacity_min'],
                    'capacity_max' => $h['capacity_max'],
                    'venue_type' => $h['venue_type'],
                    'fnb_levels' => $h['fnb_levels'],
                    'min_budget' => $h['min_budget'],
                    'base_price' => $h['base_price'],
                    'features' => $h['features'],
                    'is_active' => true,
                    'sort_order' => $i + 1,
                ]
            );
            $createdHalls[] = $hall;

            // Tiered packages (Silver / Signature / Platinum) so the client can
            // compare and pick one per hall.
            $this->seedPackagesForHall($businessId, $hall);

            $hall->media()->where('url', 'like', '%picsum%')->delete();
            if ($hall->media()->count() === 0) {
                // Tag gallery imagery by occasion (2.4/2.5.1) so the client's
                // event-type filter + cover selection have data to work with.
                $occasions = ['Wedding', 'Wedding', 'Engagement', 'Corporate'];
                foreach (range(1, 4) as $g) {
                    $photo = self::WEDDING_PHOTOS[($i * 2 + $g - 1) % count(self::WEDDING_PHOTOS)];
                    BmsHallMedia::create([
                        'business_id' => $businessId,
                        'hall_id'     => $hall->id,
                        'type'        => 'image',
                        'url'         => "https://images.unsplash.com/photo-{$photo}?auto=format&fit=crop&w=1400&q=72",
                        'title'       => $hall->name . " — {$g}",
                        'event_type'  => $occasions[$g - 1],
                        'is_cover'    => $g === 1,
                        'sort_order'  => $g,
                    ]);
                }
                // A real Askar Group wedding video (YouTube embed) per hall + an
                // elegant interior 360°. Swap for the hall's own footage / 360
                // from the back-office Media manager at go-live.
                BmsHallMedia::create([
                    'business_id' => $businessId, 'hall_id' => $hall->id, 'type' => 'video',
                    'url' => self::ASKAR_VIDEOS[$i % count(self::ASKAR_VIDEOS)], 'title' => $hall->name . ' — Askar Group',
                    'is_cover' => false, 'sort_order' => 19,
                ]);
                BmsHallMedia::create([
                    'business_id' => $businessId, 'hall_id' => $hall->id, 'type' => '360',
                    'url' => self::VENUE_360, 'title' => $hall->name . ' 360°',
                    'is_cover' => false, 'sort_order' => 20,
                ]);
            }
        }

        // ---- Add-ons (global catalog) ------------------------------------
        $addons = [
            ['name' => 'Fireworks Show', 'name_ar' => 'عرض ألعاب نارية', 'category' => 'entertainment', 'price' => 15000, 'unit' => 'show'],
            ['name' => 'Cold Sparks', 'name_ar' => 'شرارات باردة', 'category' => 'entertainment', 'price' => 6000, 'unit' => 'set'],
            ['name' => 'Extra Cinematographer', 'name_ar' => 'مصور سينمائي إضافي', 'category' => 'media', 'price' => 8000, 'unit' => 'person'],
            ['name' => 'Luxury Floral Stage', 'name_ar' => 'مسرح زهور فاخر', 'category' => 'decor', 'price' => 22000, 'unit' => 'stage'],
            ['name' => 'DJ & Sound System', 'name_ar' => 'دي جي ونظام صوت', 'category' => 'entertainment', 'price' => 12000, 'unit' => 'night'],
        ];
        $createdAddons = [];
        foreach ($addons as $i => $a) {
            $createdAddons[] = BmsAddon::firstOrCreate(
                ['business_id' => $businessId, 'name' => $a['name']],
                [
                    'name_ar' => $a['name_ar'], 'category' => $a['category'],
                    'price' => $a['price'], 'unit' => $a['unit'],
                    'is_active' => true, 'sort_order' => $i + 1,
                ]
            );
        }

        // Make every add-on available on every hall
        foreach ($createdHalls as $hall) {
            $sync = [];
            foreach ($createdAddons as $addon) {
                $sync[$addon->id] = ['business_id' => $businessId, 'is_available' => true];
            }
            $hall->addons()->syncWithoutDetaching($sync);
        }

        // ---- Matching settings (defaults) --------------------------------
        $settings = BmsMatchingSetting::resolve($businessId);
        $settings->save();

        // ---- Default task templates (logistics/kitchen/finance/ops) ------
        app(\Modules\Bms\Services\Tasks\TaskService::class)->ensureDefaults($businessId);

        // ---- Demo asset register (R2) — stored at the warehouse location --
        $assets = [
            ['code' => 'CHR-GOLD', 'name' => 'Gold Chiavari Chairs', 'name_ar' => 'كراسي شيافاري ذهبية', 'category' => 'seating', 'quantity' => 200, 'unit_value' => 350],
            ['code' => 'TBL-RND',  'name' => 'Round Banquet Tables', 'name_ar' => 'طاولات استقبال دائرية', 'category' => 'tables', 'quantity' => 40, 'unit_value' => 1200],
            ['code' => 'LGT-LED',  'name' => 'LED Par Uplights', 'name_ar' => 'إضاءة LED بار', 'category' => 'lighting', 'quantity' => 24, 'unit_value' => 900],
            ['code' => 'AV-PA',    'name' => 'Line-Array PA System', 'name_ar' => 'نظام صوت لاين أراي', 'category' => 'av', 'quantity' => 1, 'unit_value' => 85000],
            ['code' => 'DEC-CRYS', 'name' => 'Crystal Centerpiece Set', 'name_ar' => 'طقم زينة كريستال', 'category' => 'decor', 'quantity' => 30, 'unit_value' => 600],
            ['code' => 'STG-DECK', 'name' => 'Stage Deck Platforms', 'name_ar' => 'منصات مسرح', 'category' => 'staging', 'quantity' => 12, 'unit_value' => 2500],
            ['code' => 'LIN-RND',  'name' => 'Round Table Linens', 'name_ar' => 'مفارش طاولات دائرية', 'category' => 'linen', 'quantity' => 80, 'unit_value' => 150],
        ];
        $assetsCreated = 0;
        $assetSvc = app(AssetServiceContract::class);
        foreach ($assets as $a) {
            if (BmsAsset::where('business_id', $businessId)->where('code', $a['code'])->exists()) {
                continue;
            }
            $assetSvc->register($businessId, array_merge($a, [
                'location_id' => $locationId,
                'condition'   => 'good',
                'status'      => 'available',
            ]));
            $assetsCreated++;
        }

        // ---- Product-first model: كوشة variable product, buffet combo,
        //      add-on products, and relinked package items (idempotent) -------
        $this->productFirstMigrate($businessId);

        $this->command?->info('[BMS] Demo seed complete: ' . count($createdHalls) . ' halls, ' . count($createdAddons) . ' add-ons, 2 venues, 2 areas, ' . $assetsCreated . ' assets (product-first).');
    }

    /**
     * Seed three comparable packages (Silver / Signature / Platinum) for a hall
     * so the client can pick between them. Each carries the same base inclusions
     * (more in higher tiers) plus the same paid add-ons; premium tiers promote a
     * couple of add-ons to inclusions. Idempotent (firstOrCreate + item guard)
     * and links each package via the multi-hall pivot the client reads.
     */
    public function seedPackagesForHall(int $businessId, BmsHall $hall): void
    {
        $cap     = max(1, (int) $hall->capacity_max);
        $minCap  = (int) $hall->capacity_min;
        $tables  = max(1, (int) ceil($cap / 10));
        $base    = (float) ($hall->base_price ?: 50000);
        $venueId = $hall->venue_id;

        // [name, name_ar, category, qty]
        $inclusions = [
            ['Open Buffet', 'بوفيه مفتوح', 'catering', 1],
            ['Kosha (Wedding Stage)', 'كوشة', 'decor', 1],
            ['Round Tables', 'طاولات دائرية', 'furniture', $tables],
            ['Chairs', 'كراسي', 'furniture', $cap],
            ['Chair Covers', 'أغطية الكراسي', 'linen', $cap],
            ['Centerpieces', 'مفارش وسط الطاولات', 'decor', $tables],
            ['High Table', 'طاولة مرتفعة', 'furniture', 1],
            ['DJ & Sound System', 'دي جي ونظام صوت', 'entertainment', 1],
            ['Dance Floor', 'أرضية رقص', 'staging', 1],
            ['LED Screens', 'شاشات LED', 'av', 2],
            ['B-Light Uplighting', 'إضاءة محيطية', 'lighting', 1],
            ['Ceiling Drapery', 'تنسيق السقف', 'decor', 1],
            ['Catwalk', 'ممر العروسين', 'staging', 1],
            ['Lounge Area', 'منطقة جلوس', 'furniture', 1],
            ['Truss Structure', 'هيكل تراس', 'staging', 1],
        ];
        // [name, name_ar, category, qty, sale price]
        $addons = [
            ['Bubbles Machine', 'آلة فقاعات', 'effects', 1, 3500],
            ['Laser Show (In/Out Door)', 'عرض ليزر', 'effects', 1, 9000],
            ['Chocolate Fountain', 'نافورة شوكولاتة', 'catering', 1, 6000],
            ['Candlesticks', 'شمعدانات', 'decor', $tables, 120],
            ['Guest Book', 'دفتر التهاني', 'stationery', 1, 1500],
        ];

        $tiers = [
            ['name' => 'Silver Package', 'name_ar' => 'الباقة الفضية', 'fnb' => 'set_menu', 'mul' => 0.85, 'incl' => 9, 'promote' => [],
             'desc' => 'Essentials for an elegant celebration — décor, seating, catering and entertainment.',
             'desc_ar' => 'أساسيات احتفال أنيق — ديكور ومقاعد وضيافة وترفيه.'],
            ['name' => 'Signature Wedding Package', 'name_ar' => 'باقة الزفاف المميزة', 'fnb' => 'open_buffet', 'mul' => 1.0, 'incl' => 15, 'promote' => [],
             'desc' => 'An all-inclusive wedding package — décor, catering, stage and entertainment.',
             'desc_ar' => 'باقة زفاف شاملة — ديكور وضيافة وكوشة وترفيه.'],
            ['name' => 'Platinum Package', 'name_ar' => 'الباقة البلاتينية', 'fnb' => 'open_buffet', 'mul' => 1.35, 'incl' => 15, 'promote' => [0, 1],
             'desc' => 'Our premium package — every inclusion plus a laser show and bubbles, for an unforgettable night.',
             'desc_ar' => 'باقتنا المميزة — كل المكوّنات بالإضافة إلى عرض ليزر وفقاعات، لليلة لا تُنسى.'],
        ];

        foreach ($tiers as $sort => $t) {
            $pkg = BmsPackage::firstOrCreate(
                ['business_id' => $businessId, 'hall_id' => $hall->id, 'name' => $t['name']],
                [
                    'venue_id' => $venueId, 'name_ar' => $t['name_ar'],
                    'description' => $t['desc'], 'description_ar' => $t['desc_ar'],
                    'fnb_level' => $t['fnb'], 'price' => round($base * $t['mul'], -2),
                    'price_per_person' => false, 'min_pax' => $minCap, 'max_pax' => $cap,
                    'is_active' => true, 'sort_order' => $sort + 1,
                ]
            );

            // Link via the multi-hall pivot (the client resolves packages through it).
            $pkg->halls()->syncWithoutDetaching([$hall->id => ['business_id' => $businessId]]);

            if ($pkg->items()->count() > 0) {
                continue;
            }

            // Link the Open Buffet line to a combo "menu" so the client can
            // reveal its contents (dishes + qty).
            $buffetComboId = $this->buffetComboId($businessId);

            $s = 0;
            foreach (array_slice($inclusions, 0, $t['incl']) as $c) {
                BmsPackageItem::create(array_merge([
                    'business_id' => $businessId, 'package_id' => $pkg->id,
                    'product_id' => ($c[0] === 'Open Buffet' ? $buffetComboId : null),
                    'name' => $c[0], 'name_ar' => $c[1], 'category' => $c[2],
                    'quantity' => $c[3], 'qty_mode' => 'fixed', 'is_optional' => false,
                    'is_addon' => false, 'unit_cost' => 0, 'addon_price' => null, 'sort_order' => $s++,
                ], $this->itemMaterials($c[0])));
            }
            // Premium tiers include a couple of the extras at no extra charge.
            foreach ($t['promote'] as $ai) {
                $a = $addons[$ai];
                BmsPackageItem::create(array_merge([
                    'business_id' => $businessId, 'package_id' => $pkg->id,
                    'name' => $a[0], 'name_ar' => $a[1], 'category' => $a[2],
                    'quantity' => $a[3], 'qty_mode' => 'fixed', 'is_optional' => false,
                    'is_addon' => false, 'unit_cost' => (int) round($a[4] * 0.6), 'addon_price' => null, 'sort_order' => $s++,
                ], $this->itemMaterials($a[0])));
            }
            // Remaining add-ons as paid optional extras.
            foreach ($addons as $ai => $a) {
                if (in_array($ai, $t['promote'], true)) {
                    continue;
                }
                BmsPackageItem::create(array_merge([
                    'business_id' => $businessId, 'package_id' => $pkg->id,
                    'name' => $a[0], 'name_ar' => $a[1], 'category' => $a[2],
                    'quantity' => $a[3], 'qty_mode' => 'fixed', 'is_optional' => true,
                    'is_addon' => true, 'unit_cost' => (int) round($a[4] * 0.6), 'addon_price' => $a[4], 'sort_order' => $s++,
                ], $this->itemMaterials($a[0])));
            }
        }

        BmsHall::recomputePricing((int) $hall->id);
    }

    /**
     * Demo materials (description + media gallery) for notable package items, so
     * the client's info icon reveals attractive images / 360s + a description.
     * Returns [] for items without curated media.
     */
    public function itemMaterials(string $name): array
    {
        $img = fn ($id) => ['type' => 'image', 'url' => "https://images.unsplash.com/photo-{$id}?auto=format&fit=crop&w=1200&q=72"];
        $pano = fn ($title) => ['type' => '360', 'url' => self::VENUE_360, 'title' => $title];

        $map = [
            'Kosha (Wedding Stage)' => [
                'description'    => 'A handcrafted floral stage where the couple takes centre place — customizable florals, drapery and lighting.',
                'description_ar' => 'كوشة مصنوعة يدويًا يتصدّرها العروسان — زهور وتنسيق وإضاءة قابلة للتخصيص.',
                'media' => [$img('1465495976277-4387d4b0b4c6'), $img('1606216794074-735e91aa2c92'), $pano('Stage area 360°')],
                'options' => [
                    ['label' => 'Kosha #2 — Royal', 'label_ar' => 'كوشة رقم 2 — ملكية', 'price_delta' => 5000],
                    ['label' => 'Kosha #3 — Crystal', 'label_ar' => 'كوشة رقم 3 — كريستال', 'price_delta' => 12000],
                    ['label' => 'Kosha #0 — Simple', 'label_ar' => 'كوشة رقم 0 — بسيطة', 'price_delta' => -3000],
                ],
            ],
            'Open Buffet' => [
                'description'    => 'An open buffet of mixed grills, oriental dishes, live stations and a dessert corner.',
                'description_ar' => 'بوفيه مفتوح من المشويات والأطباق الشرقية وركن حلويات ومحطات حيّة.',
                // Food/buffet imagery (not generic table shots).
                'media' => [$img('1504674900247-0877df9cc836'), $img('1414235077428-338989a2e8c0'), $img('1555939594-58d7cb561ad1')],
                // Localized, quantified buffet contents. Several lines are
                // swappable — fully or partially (e.g. replace 1 of the 2 Mixed
                // Grills with Seafood Grill); swap options carry a per-unit price.
                'contents' => [
                    ['name' => 'Mixed Grills',        'name_ar' => 'مشويات مشكلة', 'quantity' => 2, 'unit' => 'chafing dishes', 'unit_ar' => 'سفنديش',
                        'swap_options' => [
                            ['name' => 'Seafood Grill',    'name_ar' => 'مشويات بحرية',  'price_delta' => 1500],
                            ['name' => 'Premium Steak',    'name_ar' => 'ستيك فاخر',     'price_delta' => 2500],
                        ]],
                    ['name' => 'Grilled Chicken',     'name_ar' => 'دجاج مشوي',    'quantity' => 2, 'unit' => 'chafing dishes', 'unit_ar' => 'سفنديش',
                        'swap_options' => [
                            ['name' => 'Grilled Lamb Chops', 'name_ar' => 'ريش ضأن مشوية', 'price_delta' => 1200],
                            ['name' => 'Stuffed Pigeon',     'name_ar' => 'حمام محشي',     'price_delta' => 900],
                        ]],
                    ['name' => 'Rice & Pasta',        'name_ar' => 'أرز ومكرونة',  'quantity' => 2, 'unit' => 'chafing dishes', 'unit_ar' => 'سفنديش'],
                    ['name' => 'Salad Bar',           'name_ar' => 'ركن السلطات',  'quantity' => 1, 'unit' => 'station', 'unit_ar' => 'ركن',
                        'swap_options' => [
                            ['name' => 'Soups Corner',     'name_ar' => 'ركن الشوربات',  'price_delta' => 0],
                            ['name' => 'Mezze Selection',  'name_ar' => 'تشكيلة مقبلات', 'price_delta' => 0],
                            ['name' => 'Cheese & Cold Cuts','name_ar' => 'أجبان ومشهيات', 'price_delta' => 800],
                        ]],
                    ['name' => 'Dessert Table',       'name_ar' => 'ركن الحلويات',  'quantity' => 1, 'unit' => 'station', 'unit_ar' => 'ركن'],
                    ['name' => 'Juices & Soft Drinks','name_ar' => 'عصائر ومشروبات','quantity' => 1, 'unit' => 'station', 'unit_ar' => 'ركن'],
                ],
            ],
            'DJ & Sound System' => [
                'description'    => 'Professional DJ with a premium line-array sound system to keep the night alive.',
                'description_ar' => 'دي جي محترف مع نظام صوت احترافي للحفاظ على أجواء الليلة.',
                'media' => [$img('1519671482749-fd09be7ccebf')],
            ],
            'Dance Floor' => [
                'description'    => 'A spacious lit dance floor at the heart of the celebration.',
                'description_ar' => 'أرضية رقص واسعة ومضاءة في قلب الاحتفال.',
                'media' => [$img('1511795409834-ef04bbd61622')],
            ],
            'LED Screens' => [
                'description'    => 'Large LED screens for live feeds, photos and visuals.',
                'description_ar' => 'شاشات LED كبيرة للبث المباشر والصور والعروض.',
                'media' => [$img('1507504031003-b417219a0fde')],
            ],
            'Centerpieces' => [
                'description'    => 'Elegant floral centerpieces for every table.',
                'description_ar' => 'تنسيقات زهور أنيقة لكل طاولة.',
                'media' => [$img('1606216794074-735e91aa2c92')],
            ],
            'Laser Show (In/Out Door)' => [
                'description'    => 'A choreographed laser & light show for the grand entrance.',
                'description_ar' => 'عرض ليزر وإضاءة متناغم لدخول مميز.',
                'media' => [$img('1606216794074-735e91aa2c92'), $pano('Hall lit 360°')],
            ],
            'Chocolate Fountain' => [
                'description'    => 'A flowing chocolate fountain with fresh fruit and treats.',
                'description_ar' => 'نافورة شوكولاتة متدفقة مع فواكه طازجة وتشكيلة حلويات.',
                'media' => [$img('1464366400600-7168b8af9bc3')],
            ],
        ];

        return $map[$name] ?? [];
    }

    /** Cached id of the demo "Open Buffet Menu" combo product (false = unresolved). */
    protected $buffetComboCache = false;

    protected function buffetComboId(int $businessId): ?int
    {
        if ($this->buffetComboCache === false) {
            $this->buffetComboCache = $this->ensureBuffetCombo($businessId);
        }
        return $this->buffetComboCache ?: null;
    }

    /**
     * Create (once) a demo "Open Buffet Menu" combo product made of several
     * food components, so the client hall page can reveal the buffet's contents
     * + quantities. Returns the combo product id (idempotent by name).
     */
    protected function ensureBuffetCombo(int $businessId): ?int
    {
        $existing = \App\Product::where('business_id', $businessId)->where('type', 'combo')
            ->where('name', 'Open Buffet Menu')->value('id');
        if ($existing) {
            return (int) $existing;
        }

        $userId = (int) (\App\User::where('business_id', $businessId)->value('id') ?: 0);
        $unitId = (int) (\DB::table('units')->where('business_id', $businessId)->value('id') ?: 1);

        // Food components -> their variation ids.
        $components = [
            ['Mixed Grills', 'مشويات مشكلة', 120, 180],
            ['Grilled Chicken', 'دجاج مشوي', 80, 120],
            ['Rice & Pasta', 'أرز ومعكرونة', 25, 40],
            ['Salad Bar', 'ركن السلطات', 30, 50],
            ['Dessert Table', 'ركن الحلويات', 40, 70],
            ['Juices & Soft Drinks', 'عصائر ومشروبات', 20, 35],
        ];
        $comboVariations = [];
        foreach ($components as $c) {
            $varId = $this->makeSimpleProduct($businessId, $userId, $unitId, $c[0], $c[2], $c[3]);
            $comboVariations[] = ['variation_id' => (string) $varId, 'quantity' => 1, 'unit_id' => (string) $unitId];
        }

        // The combo product itself.
        $comboId = $this->makeSimpleProduct($businessId, $userId, $unitId, 'Open Buffet Menu', 315, 350, 'combo', $comboVariations);
        return (int) \DB::table('variations')->where('id', $comboId)->value('product_id');
    }

    /**
     * Create a variable UltimatePOS product with N priced variations.
     * @param array $variants  [['name'=>, 'cost'=>, 'sell'=>], ...]; first = default/base.
     * @return array{product_id:int, variations:array<string,int>}  name => variation_id
     */
    protected function makeVariableProduct(int $businessId, int $userId, int $unitId, string $name, array $variants): array
    {
        $productId = \DB::table('products')->insertGetId([
            'name'         => $name, 'business_id' => $businessId, 'type' => 'variable', 'unit_id' => $unitId,
            'sku'          => 'BMS' . strtoupper(substr(md5($name . $businessId), 0, 8)),
            'barcode_type' => 'C128', 'tax_type' => 'exclusive', 'enable_stock' => 0, 'alert_quantity' => 0,
            'is_inactive'  => 0, 'not_for_selling' => 0, 'created_by' => $userId, 'created_at' => now(), 'updated_at' => now(),
        ]);
        $pvId = \DB::table('product_variations')->insertGetId([
            'name' => $name, 'product_id' => $productId, 'is_dummy' => 0, 'created_at' => now(), 'updated_at' => now(),
        ]);

        $out = [];
        foreach ($variants as $v) {
            $vid = \DB::table('variations')->insertGetId([
                'name'                   => $v['name'],
                'product_id'             => $productId,
                'sub_sku'                => 'BMS' . strtoupper(substr(md5($name . $v['name'] . $productId), 0, 8)),
                'product_variation_id'   => $pvId,
                'default_purchase_price' => $v['cost'], 'dpp_inc_tax' => $v['cost'], 'profit_percent' => 0,
                'default_sell_price'     => $v['sell'], 'sell_price_inc_tax' => $v['sell'],
                'created_at' => now(), 'updated_at' => now(),
            ]);
            $out[$v['name']] = (int) $vid;
        }

        return ['product_id' => (int) $productId, 'variations' => $out];
    }

    /**
     * Minimal UltimatePOS product (single or combo) with its dummy variation.
     * Returns the created variation id (so combos can reference components).
     */
    protected function makeSimpleProduct(int $businessId, int $userId, int $unitId, string $name, float $cost, float $sell, string $type = 'single', array $comboVariations = []): int
    {
        $productId = \DB::table('products')->insertGetId([
            'name'            => $name,
            'business_id'     => $businessId,
            'type'            => $type,
            'unit_id'         => $unitId,
            'sku'             => 'BMS' . strtoupper(substr(md5($name . $businessId), 0, 8)),
            'barcode_type'    => 'C128',
            'tax_type'        => 'exclusive',
            'enable_stock'    => 0,
            'alert_quantity'  => 0,
            'is_inactive'     => 0,
            'not_for_selling' => 0,
            'created_by'      => $userId,
            'created_at'      => now(),
            'updated_at'      => now(),
        ]);

        $pvId = \DB::table('product_variations')->insertGetId([
            'name' => 'DUMMY', 'product_id' => $productId, 'is_dummy' => 1,
            'created_at' => now(), 'updated_at' => now(),
        ]);

        return \DB::table('variations')->insertGetId([
            'name'                   => 'DUMMY',
            'product_id'             => $productId,
            'sub_sku'                => 'BMS' . strtoupper(substr(md5($name . $productId), 0, 8)),
            'product_variation_id'   => $pvId,
            'default_purchase_price' => $cost,
            'dpp_inc_tax'            => $cost,
            'profit_percent'         => 0,
            'default_sell_price'     => $sell,
            'sell_price_inc_tax'     => $sell,
            'combo_variations'       => json_encode($comboVariations),
            'created_at'             => now(),
            'updated_at'             => now(),
        ]);
    }

    /**
     * Migrate the demo to the product-first model (idempotent): كوشة → a real
     * variable product (swaps = variations), buffet combo enriched (localized
     * components + serving qty/unit), global add-ons → is_addon products, and
     * the package items relinked so they inherit from the products. Re-runnable;
     * call from a fresh seed or as a backfill (tinker) on existing data.
     *
     * @return array  human-readable log of what changed
     */
    public function productFirstMigrate(int $businessId): array
    {
        $uid    = (int) (\App\User::where('business_id', $businessId)->value('id') ?: 0);
        $unitId = (int) (\DB::table('units')->where('business_id', $businessId)->value('id') ?: 1);
        $img    = fn ($id) => ['type' => 'image', 'url' => "https://images.unsplash.com/photo-{$id}?auto=format&fit=crop&w=1200&q=72"];
        $log    = [];

        // 1) كوشة as a variable product (variations supply the swap options).
        $koshaPid = \App\Product::where('business_id', $businessId)->where('type', 'variable')
            ->where('name', 'Kosha (Wedding Stage)')->value('id');
        if (! $koshaPid) {
            $vp = $this->makeVariableProduct($businessId, $uid, $unitId, 'Kosha (Wedding Stage)', [
                ['name' => 'Number 1', 'cost' => 12000, 'sell' => 20000], // base
                ['name' => 'Royal',    'cost' => 16000, 'sell' => 25000], // +5000
                ['name' => 'Crystal',  'cost' => 20000, 'sell' => 32000], // +12000
                ['name' => 'Simple',   'cost' => 10000, 'sell' => 17000], // -3000
            ]);
            $koshaPid = $vp['product_id'];
            $v = $vp['variations'];
            \Modules\Bms\Entities\BmsProductMeta::forProduct($businessId, $koshaPid)->fill([
                'business_id' => $businessId, 'name_ar' => 'كوشة',
                'variation_labels_ar' => [
                    (string) $v['Number 1'] => 'رقم 1', (string) $v['Royal'] => 'ملكية',
                    (string) $v['Crystal'] => 'كريستال', (string) $v['Simple'] => 'بسيطة',
                ],
            ])->save();
            $this->addProductMedia($businessId, $koshaPid, [
                $img(self::WEDDING_PHOTOS[2]), $img(self::WEDDING_PHOTOS[5]),
                ['type' => '360', 'url' => self::VENUE_360, 'title' => 'Stage 360°'],
            ]);
            $log[] = 'كوشة variable product created (#' . $koshaPid . ')';
        }
        $koshaBaseVar = (int) \DB::table('variations')->where('product_id', $koshaPid)->orderBy('id')->value('id');

        // 2) Buffet combo: localize components + serving qty/unit; combo media.
        $comboPid = $this->buffetComboId($businessId);
        if ($comboPid) {
            $compMap = [
                'Mixed Grills' => ['مشويات مشكلة', 2, 'سفنديش'], 'Grilled Chicken' => ['دجاج مشوي', 2, 'سفنديش'],
                'Rice & Pasta' => ['أرز ومعكرونة', 2, 'سفنديش'], 'Salad Bar' => ['ركن السلطات', 1, 'ركن'],
                'Dessert Table' => ['ركن الحلويات', 1, 'ركن'], 'Juices & Soft Drinks' => ['عصائر ومشروبات', 1, 'ركن'],
            ];
            $combo = \App\Product::with('variations')->find($comboPid);
            $cv = optional($combo->variations->first())->combo_variations ?? [];
            $vars = \App\Variation::whereIn('id', array_map(fn ($r) => (int) ($r['variation_id'] ?? 0), $cv))
                ->with('product:id,name')->get()->keyBy('id');
            foreach ($cv as &$row) {
                $cvar = $vars->get((int) ($row['variation_id'] ?? 0));
                $nm = optional(optional($cvar)->product)->name;
                if ($nm && isset($compMap[$nm])) {
                    [$nameAr, $qty, $unitAr] = $compMap[$nm];
                    \Modules\Bms\Entities\BmsProductMeta::forProduct($businessId, $cvar->product_id)
                        ->fill(['business_id' => $businessId, 'name_ar' => $nameAr, 'default_unit_ar' => $unitAr, 'addon_unit' => 'station'])->save();
                    $row['quantity'] = $qty;
                }
            }
            unset($row);
            \DB::table('variations')->where('product_id', $comboPid)->update(['combo_variations' => json_encode(array_values($cv))]);
            \Modules\Bms\Entities\BmsProductMeta::forProduct($businessId, $comboPid)
                ->fill(['business_id' => $businessId, 'name_ar' => 'بوفيه مفتوح'])->save();
            if (! \Modules\Bms\Entities\BmsProductMedia::where('product_id', $comboPid)->exists()) {
                $this->addProductMedia($businessId, $comboPid, [
                    $img('1504674900247-0877df9cc836'), $img('1414235077428-338989a2e8c0'), $img('1555939594-58d7cb561ad1'),
                ]);
            }
            $log[] = 'buffet combo enriched (#' . $comboPid . ')';
        }

        // 3) Relink package items so they inherit from the products.
        \Modules\Bms\Entities\BmsPackageItem::where('business_id', $businessId)->where('name', 'Kosha (Wedding Stage)')
            ->update(['product_id' => $koshaPid, 'variation_id' => $koshaBaseVar, 'options' => null]);
        // Keep the curated `contents` as a swap/units OVERLAY: the combo product
        // supplies the buffet membership (product-first), while the item's
        // contents add swap_options (substitution) + Arabic unit labels the
        // combo lacks — and the server reads it for swap-pricing integrity.
        \Modules\Bms\Entities\BmsPackageItem::where('business_id', $businessId)->where('name', 'Open Buffet')
            ->update(['product_id' => $comboPid]);
        $log[] = 'package items relinked (كوشة + buffet)';

        // 4) Global add-ons → is_addon products (the Add-ons page is product-first).
        foreach (\Modules\Bms\Entities\BmsAddon::where('business_id', $businessId)->get() as $ad) {
            if ($ad->product_id) {
                continue;
            }
            $varId = $this->makeSimpleProduct($businessId, $uid, $unitId, $ad->name, (float) $ad->price * 0.6, (float) $ad->price);
            $pid = (int) \DB::table('variations')->where('id', $varId)->value('product_id');
            \Modules\Bms\Entities\BmsProductMeta::forProduct($businessId, $pid)->fill([
                'business_id' => $businessId, 'name_ar' => $ad->name_ar, 'is_addon' => true,
                'addon_price' => $ad->price, 'addon_unit' => $ad->unit,
            ])->save();
            $this->addProductMedia($businessId, $pid, [$img(self::WEDDING_PHOTOS[3])]);
            $ad->forceFill(['product_id' => $pid])->save();
        }
        $log[] = 'global add-ons linked to products';

        return $log;
    }

    /** Insert marketing media rows for a product (first = cover). */
    protected function addProductMedia(int $businessId, int $productId, array $items): void
    {
        $s = 0;
        foreach ($items as $m) {
            \Modules\Bms\Entities\BmsProductMedia::create([
                'business_id' => $businessId, 'product_id' => $productId, 'type' => $m['type'],
                'url' => $m['url'], 'title' => $m['title'] ?? null, 'is_cover' => $s === 0, 'sort_order' => $s++,
            ]);
        }
    }
}
