<?php

namespace Database\Seeders;

use App\Models\Booking;
use App\Models\Chef;
use App\Models\Cuisine;
use App\Models\Customer;
use App\Models\DietaryPlan;
use App\Models\Expense;
use App\Models\HousekeepingTask;
use App\Models\InventoryItem;
use App\Models\Membership;
use App\Models\MembershipPlan;
use App\Models\MenuCategory;
use App\Models\MenuItem;
use App\Models\Order;
use App\Models\Payment;
use App\Models\PurchaseOrder;
use App\Models\Referral;
use App\Models\RewardTransaction;
use App\Models\Room;
use App\Models\RoomType;
use App\Models\Setting;
use App\Models\StockMovement;
use App\Models\Supplier;
use App\Models\User;
use App\Models\Vendor;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // ------------------------------------------------ Platform (SaaS layer)
        $plans = collect([
            ['Starter', 25000, 15, ['Front desk & bookings', 'POS + kitchen/bar displays', 'Housekeeping', 'Email notifications']],
            ['Growth', 60000, 50, ['Everything in Starter', 'Inventory & procurement', 'Memberships & rewards', 'Marketplace listing', 'Online payments']],
            ['Enterprise', 120000, 1000, ['Everything in Growth', 'Custom domain & branding', 'WhatsApp notifications', 'Priority support', 'Owner daily digest']],
        ])->map(fn ($p) => \App\Models\PlatformPlan::create([
            'name' => $p[0], 'price_monthly' => $p[1], 'max_rooms' => $p[2], 'features' => $p[3],
        ]));

        $flagship = \App\Models\Hotel::create([
            'name' => 'Epelcon Grand Hotel Abuja',
            'slug' => 'grand-abuja',
            'email' => 'hello@epelcon.com',
            'phone' => '+234 800 000 0000',
            'address' => '12 Epelcon Boulevard, Abuja, Nigeria',
            'city' => 'Abuja',
            'platform_plan_id' => $plans[2]->id,
            'status' => 'active',
            'subscription_expires_at' => now()->addYear(),
        ]);

        \App\Models\Hotel::create([
            'name' => 'Epelcon Lagos Beachfront',
            'slug' => 'lagos-beachfront',
            'email' => 'lagos@epelcon.com',
            'phone' => '+234 811 222 3333',
            'city' => 'Lagos',
            'platform_plan_id' => $plans[1]->id,
            'status' => 'trial',
            'trial_ends_at' => now()->addDays(14),
        ]);

        User::create([
            'name' => 'Achimugu A. Emmanuel',
            'email' => 'owner@epelcon.com',
            'password' => Hash::make('password'),
            'role' => 'super_admin',
            'status' => 'active',
            'department' => 'Platform',
            'referral_code' => strtoupper(Str::random(8)),
        ]);

        User::create([
            'name' => 'Lagos Admin',
            'email' => 'lagos.admin@epelcon.com',
            'password' => Hash::make('password'),
            'role' => 'admin',
            'hotel_id' => 2,
            'status' => 'active',
            'department' => 'Management',
            'referral_code' => strtoupper(Str::random(8)),
        ]);

        // Everything below seeds into the flagship hotel.
        \App\Support\Tenancy::set($flagship);

        // ------------------------------------------------ Settings
        foreach ([
            'hotel_name' => 'Epelcon Hospitality',
            'currency' => '₦',
            'tax_percent' => '7.5',
            'address' => '12 Epelcon Boulevard, Abuja, Nigeria',
            'phone' => '+234 800 000 0000',
            'email' => 'hello@epelcon.com',
            'checkin_time' => '14:00',
            'checkout_time' => '12:00',
            'referral_points' => '50',
        ] as $key => $value) {
            Setting::put($key, $value);
        }

        // ------------------------------------------------ Staff accounts
        $staff = [];

        foreach ([
            ['Adaeze Epelcon', 'admin@epelcon.com', 'admin', 'Management'],
            ['Tunde Bello', 'manager@epelcon.com', 'manager', 'Management'],
            ['Ngozi Okafor', 'supervisor@epelcon.com', 'supervisor', 'Operations'],
            ['Ibrahim Musa', 'accountant@epelcon.com', 'accountant', 'Finance'],
            ['Blessing Adeyemi', 'reception@epelcon.com', 'receptionist', 'Front Office'],
            ['Chef Emeka Obi', 'chef@epelcon.com', 'chef', 'Kitchen'],
            ['Kunle Ajayi', 'kitchen@epelcon.com', 'kitchen', 'Kitchen'],
            ['Sandra George', 'bar@epelcon.com', 'bartender', 'Bar'],
            ['David Okon', 'waiter@epelcon.com', 'waiter', 'Restaurant'],
            ['Mary Danladi', 'housekeeping@epelcon.com', 'housekeeper', 'Housekeeping'],
            ['Peter Eze', 'store@epelcon.com', 'storekeeper', 'Stores'],
            ['Fatima Sule', 'procurement@epelcon.com', 'procurement', 'Procurement'],
        ] as [$name, $email, $role, $dept]) {
            $staff[$role] = User::create([
                'name' => $name,
                'email' => $email,
                'password' => Hash::make('password'),
                'role' => $role,
                'hotel_id' => $flagship->id,
                'department' => $dept,
                'status' => 'active',
                'referral_code' => strtoupper(Str::random(8)),
                'phone' => '+234 80' . rand(10000000, 99999999),
            ]);
        }

        $demoUser = User::create([
            'name' => 'Chinedu Guest',
            'email' => 'customer@epelcon.com',
            'password' => Hash::make('password'),
            'role' => 'customer',
            'status' => 'active',
            'referral_code' => 'EPELCON1',
            'phone' => '+234 8033334444',
        ]);

        // ------------------------------------------------ Rooms
        $types = collect([
            ['Standard Room', 45000, 2, 1, 24, ['Air conditioning', 'Free Wi-Fi', 'Smart TV', 'Work desk'], 'Cosy comfort with everything you need for a restful stay.'],
            ['Deluxe Room', 75000, 2, 2, 32, ['King bed', 'City view', 'Mini bar', 'Rain shower', 'Free Wi-Fi'], 'Extra space and elegant finishing with a stunning city view.'],
            ['Executive Suite', 130000, 3, 2, 48, ['Separate living area', 'Jacuzzi', 'Espresso machine', 'Butler service'], 'A private living room, premium amenities and dedicated service.'],
            ['Presidential Suite', 300000, 4, 3, 96, ['Panoramic terrace', 'Private dining', 'Personal chef on request', 'Jacuzzi & sauna'], 'Our flagship suite — unmatched luxury for distinguished guests.'],
        ])->map(fn ($t) => RoomType::create([
            'name' => $t[0], 'slug' => Str::slug($t[0]), 'base_price' => $t[1],
            'capacity_adults' => $t[2], 'capacity_children' => $t[3], 'size_sqm' => $t[4],
            'amenities' => $t[5], 'description' => $t[6],
        ]));

        $rooms = collect();
        $numbering = [[1, 8, 0], [2, 6, 1], [3, 4, 2], [4, 2, 3]]; // floor, count, type index

        foreach ($numbering as [$floor, $count, $typeIdx]) {
            foreach (range(1, $count) as $i) {
                $rooms->push(Room::create([
                    'room_type_id' => $types[$typeIdx]->id,
                    'number' => $floor . str_pad($i, 2, '0', STR_PAD_LEFT),
                    'floor' => 'Floor ' . $floor,
                    'status' => 'available',
                    'housekeeping_status' => 'clean',
                ]));
            }
        }

        // ------------------------------------------------ Customers
        $customerData = [
            ['Chinedu Guest', 'customer@epelcon.com', $demoUser->id, true],
            ['Amaka Nwosu', 'amaka@example.com', null, true],
            ['John Adewale', 'john.a@example.com', null, false],
            ['Grace Effiong', 'grace.e@example.com', null, false],
            ['Mohammed Bala', 'm.bala@example.com', null, false],
            ['Helen Ojo', 'helen.ojo@example.com', null, false],
            ['Sunday Igwe', 'sunday.i@example.com', null, false],
            ['Rita Umeh', 'rita.u@example.com', null, false],
        ];

        $customers = collect($customerData)->map(fn ($c) => Customer::create([
            'name' => $c[0], 'email' => $c[1], 'user_id' => $c[2], 'vip' => $c[3],
            'phone' => '+234 81' . rand(10000000, 99999999),
            'city' => collect(['Abuja', 'Lagos', 'Port Harcourt', 'Enugu'])->random(),
            'country' => 'Nigeria',
        ]));

        // ------------------------------------------------ Bookings
        $today = Carbon::today();

        $mkBooking = function ($customer, $room, $in, $out, $status, $paidRatio = 1) use ($staff) {
            $nights = max(1, $in->diffInDays($out));
            $total = $nights * (float) $room->roomType->base_price;

            return Booking::create([
                'code' => 'BK-' . strtoupper(Str::random(6)),
                'customer_id' => $customer->id,
                'room_type_id' => $room->room_type_id,
                'room_id' => $room->id,
                'check_in' => $in,
                'check_out' => $out,
                'adults' => rand(1, 2),
                'children' => rand(0, 1),
                'status' => $status,
                'source' => collect(['walk_in', 'website', 'phone'])->random(),
                'total_amount' => $total,
                'paid_amount' => round($total * $paidRatio, 2),
                'created_by' => $staff['receptionist']->id,
                'checked_in_at' => in_array($status, ['checked_in', 'checked_out']) ? $in->copy()->setTime(14, 0) : null,
                'checked_out_at' => $status === 'checked_out' ? $out->copy()->setTime(11, 30) : null,
            ]);
        };

        $rooms = $rooms->values();

        // In-house guests
        foreach ([0, 9, 15] as $idx => $roomIdx) {
            $mkBooking($customers[$idx + 1], $rooms[$roomIdx], $today->copy()->subDays(rand(1, 3)), $today->copy()->addDays(rand(1, 4)), 'checked_in', 0.6);
            $rooms[$roomIdx]->update(['status' => 'occupied']);
        }

        // Arriving today
        $mkBooking($customers[4], $rooms[3], $today->copy(), $today->copy()->addDays(2), 'confirmed', 0.5);
        $mkBooking($customers[5], $rooms[10], $today->copy(), $today->copy()->addDays(3), 'confirmed', 0);
        $rooms[3]->update(['status' => 'reserved']);
        $rooms[10]->update(['status' => 'reserved']);

        // Future & past bookings
        $mkBooking($customers[6], $rooms[16], $today->copy()->addDays(3), $today->copy()->addDays(6), 'pending', 0);
        $mkBooking($customers[7], $rooms[1], $today->copy()->subDays(10), $today->copy()->subDays(7), 'checked_out');
        $mkBooking($customers[0], $rooms[11], $today->copy()->subDays(6), $today->copy()->subDays(4), 'checked_out');

        // Housekeeping
        $rooms[1]->update(['housekeeping_status' => 'dirty']);
        $rooms[5]->update(['housekeeping_status' => 'dirty']);
        $rooms[19]->update(['status' => 'maintenance', 'housekeeping_status' => 'out_of_service']);

        foreach ([
            [$rooms[1]->id, 'cleaning', 'high', 'pending'],
            [$rooms[5]->id, 'cleaning', 'normal', 'pending'],
            [$rooms[9]->id, 'turndown', 'normal', 'in_progress'],
            [$rooms[19]->id, 'maintenance', 'urgent', 'in_progress'],
            [$rooms[2]->id, 'inspection', 'low', 'completed'],
        ] as [$roomId, $type, $priority, $status]) {
            HousekeepingTask::create([
                'room_id' => $roomId, 'task_type' => $type, 'priority' => $priority, 'status' => $status,
                'assigned_to' => $staff['housekeeper']->id, 'scheduled_for' => $today,
                'completed_at' => $status === 'completed' ? now() : null,
            ]);
        }

        // ------------------------------------------------ Cuisine & menu
        $cuisines = collect(['Nigerian', 'Continental', 'Chinese', 'Italian', 'Grill & BBQ'])
            ->map(fn ($n) => Cuisine::create(['name' => $n, 'slug' => Str::slug($n)]));

        $cats = collect([
            ['Breakfast', 'food'], ['Soups & Swallow', 'food'], ['Rice Dishes', 'food'],
            ['Grills & Proteins', 'food'], ['Pasta & Continental', 'food'], ['Desserts', 'food'],
            ['Cocktails', 'drink'], ['Wines & Spirits', 'drink'], ['Beers', 'drink'], ['Juices & Soft Drinks', 'drink'],
        ])->mapWithKeys(fn ($c, $i) => [$c[0] => MenuCategory::create(['name' => $c[0], 'type' => $c[1], 'sort_order' => $i])]);

        $chefs = collect([
            ['Chef Emeka Obi', 'Executive Chef', $staff['chef']->id, 'Nigerian fine dining, fusion cuisine', 15, 4.9, true, 'Trained in Lagos and London, Chef Emeka leads our kitchen with a passion for elevating Nigerian classics.'],
            ['Chef Amina Yusuf', 'Sous Chef', null, 'Continental, pastries & desserts', 9, 4.7, true, 'Amina\'s pastries have won three national awards. She runs our breakfast and dessert programme.'],
            ['Chef Li Wei', 'Speciality Chef', null, 'Chinese & Asian fusion', 12, 4.8, false, 'Chef Li brings authentic wok mastery and dim sum artistry to Epelcon.'],
        ])->map(fn ($c) => Chef::create([
            'name' => $c[0], 'title' => $c[1], 'user_id' => $c[2], 'specialties' => $c[3],
            'years_experience' => $c[4], 'rating' => $c[5], 'featured' => $c[6], 'bio' => $c[7],
        ]));

        $menu = [
            // name, category, cuisine idx, chef idx, price, tags, featured, spice
            ['Full Nigerian Breakfast', 'Breakfast', 0, 0, 8500, [], true, 1],
            ['Akara & Pap', 'Breakfast', 0, 0, 4500, ['vegetarian'], false, 0],
            ['English Breakfast', 'Breakfast', 1, 1, 9500, [], false, 0],
            ['Egusi Soup & Pounded Yam', 'Soups & Swallow', 0, 0, 12000, [], true, 2],
            ['Afang Soup & Eba', 'Soups & Swallow', 0, 0, 11500, [], false, 2],
            ['Ogbono Soup & Semo', 'Soups & Swallow', 0, 0, 11000, [], false, 2],
            ['Smoky Party Jollof Rice', 'Rice Dishes', 0, 0, 9500, ['halal'], true, 2],
            ['Fried Rice Royale', 'Rice Dishes', 0, 0, 9500, [], false, 1],
            ['Coconut Rice & Grilled Chicken', 'Rice Dishes', 0, 0, 10500, ['gluten_free'], false, 1],
            ['Native Rice (Iwuk Edesi)', 'Rice Dishes', 0, 0, 10000, [], false, 2],
            ['Suya Platter', 'Grills & Proteins', 4, 0, 13500, ['halal', 'low_carb'], true, 3],
            ['Grilled Croaker Fish', 'Grills & Proteins', 4, 0, 16500, ['gluten_free', 'low_carb'], true, 2],
            ['Asun (Spicy Goat Meat)', 'Grills & Proteins', 4, 0, 12500, ['halal'], false, 4],
            ['BBQ Chicken Wings', 'Grills & Proteins', 4, 2, 9500, [], false, 2],
            ['Kung Pao Chicken', 'Pasta & Continental', 2, 2, 11500, [], false, 3],
            ['Spaghetti Bolognese', 'Pasta & Continental', 3, 1, 10500, [], false, 0],
            ['Penne Alfredo with Shrimp', 'Pasta & Continental', 3, 1, 12500, [], false, 0],
            ['Vegan Buddha Bowl', 'Pasta & Continental', 1, 1, 9000, ['vegan', 'gluten_free', 'dairy_free'], false, 0],
            ['Chocolate Lava Cake', 'Desserts', 1, 1, 6500, ['vegetarian'], true, 0],
            ['Puff-Puff & Ice Cream', 'Desserts', 0, 1, 5000, ['vegetarian'], false, 0],
            ['Fruit Parfait', 'Desserts', 1, 1, 5500, ['vegetarian', 'gluten_free'], false, 0],
        ];

        foreach ($menu as $m) {
            MenuItem::create([
                'name' => $m[0], 'slug' => Str::slug($m[0]),
                'menu_category_id' => $cats[$m[1]]->id,
                'cuisine_id' => $cuisines[$m[2]]->id,
                'chef_id' => $chefs[$m[3]]->id,
                'type' => 'food', 'station' => 'kitchen',
                'price' => $m[4], 'cost' => round($m[4] * 0.45),
                'dietary_tags' => $m[5], 'featured' => $m[6], 'spice_level' => $m[7],
                'prep_time_minutes' => rand(15, 40),
                'description' => 'Prepared fresh by our culinary team.',
            ]);
        }

        $drinks = [
            ['Chapman Royale', 'Cocktails', 6500, true],
            ['Epelcon Signature Mojito', 'Cocktails', 8000, true],
            ['Piña Colada', 'Cocktails', 8500, false],
            ['Virgin Strawberry Daiquiri', 'Cocktails', 6000, false],
            ['Red Wine (Glass)', 'Wines & Spirits', 7500, false],
            ['Champagne (Bottle)', 'Wines & Spirits', 95000, false],
            ['Premium Whisky (Shot)', 'Wines & Spirits', 9000, false],
            ['Local Lager', 'Beers', 2500, false],
            ['Imported Stout', 'Beers', 3500, false],
            ['Craft IPA', 'Beers', 4500, false],
            ['Fresh Orange Juice', 'Juices & Soft Drinks', 4000, false],
            ['Zobo Refresher', 'Juices & Soft Drinks', 3000, false],
            ['Smoothie of the Day', 'Juices & Soft Drinks', 5500, false],
            ['Soft Drink (Can)', 'Juices & Soft Drinks', 1500, false],
        ];

        foreach ($drinks as $d) {
            MenuItem::create([
                'name' => $d[0], 'slug' => Str::slug($d[0]),
                'menu_category_id' => $cats[$d[1]]->id,
                'type' => 'drink', 'station' => 'bar',
                'price' => $d[2], 'cost' => round($d[2] * 0.4),
                'featured' => $d[3], 'dietary_tags' => [],
                'prep_time_minutes' => 5,
            ]);
        }

        // ------------------------------------------------ Dietary plans
        foreach ([
            ['Lean & Light', 'Calorie-controlled meals built around lean proteins and vegetables.', 'Weight management', 1500, 45000, 7],
            ['Diabetic Friendly', 'Low-GI meals reviewed by our nutrition consultant.', 'Blood sugar control', 1800, 52000, 7],
            ['Plant Power (Vegan)', 'Fully plant-based rotation with complete proteins.', 'Plant-based living', 2000, 48000, 7],
            ['Executive Fuel', 'High-protein, brain-boosting meals for busy professionals.', 'Energy & focus', 2200, 60000, 14],
        ] as $p) {
            DietaryPlan::create([
                'name' => $p[0], 'description' => $p[1], 'goal' => $p[2],
                'daily_calories' => $p[3], 'price' => $p[4], 'duration_days' => $p[5],
                'meals' => [
                    'breakfast' => 'Chef-selected rotation',
                    'lunch' => 'Chef-selected rotation',
                    'dinner' => 'Chef-selected rotation',
                ],
            ]);
        }

        // ------------------------------------------------ Suppliers & inventory
        $suppliers = collect([
            ['Farmfresh Produce Ltd', 'Food & Produce'],
            ['Prime Beverages Nig.', 'Beverages'],
            ['CleanLinen Services', 'Linen & Laundry'],
            ['TotalEquip Hospitality', 'Equipment'],
        ])->map(fn ($s) => Supplier::create([
            'name' => $s[0], 'category' => $s[1], 'status' => 'active',
            'contact_person' => 'Sales Desk', 'phone' => '+234 90' . rand(10000000, 99999999),
            'email' => Str::slug($s[0]) . '@example.com', 'rating' => rand(35, 50) / 10,
        ]));

        $inventory = [
            ['Rice (50kg bag)', 'Food', 'bags', 12, 5, 85000, 'main_store', 0],
            ['Vegetable Oil (25L)', 'Food', 'kegs', 8, 4, 62000, 'kitchen', 0],
            ['Frozen Chicken (kg)', 'Food', 'kg', 45, 20, 4800, 'kitchen', 0],
            ['Croaker Fish (kg)', 'Food', 'kg', 18, 10, 6500, 'kitchen', 0],
            ['Tomato Paste (carton)', 'Food', 'cartons', 3, 5, 28000, 'main_store', 0],
            ['Local Lager (crate)', 'Beverage', 'crates', 25, 10, 15000, 'bar', 1],
            ['Red Wine (bottle)', 'Beverage', 'bottles', 30, 12, 12000, 'bar', 1],
            ['Champagne (bottle)', 'Beverage', 'bottles', 6, 4, 65000, 'bar', 1],
            ['Soft Drinks (crate)', 'Beverage', 'crates', 14, 8, 6000, 'bar', 1],
            ['Bath Towels', 'Housekeeping', 'pcs', 120, 40, 4500, 'housekeeping', 2],
            ['Bed Sheets (set)', 'Housekeeping', 'sets', 60, 25, 12000, 'housekeeping', 2],
            ['Toiletries Kit', 'Housekeeping', 'kits', 15, 30, 2500, 'housekeeping', 2],
            ['Detergent (20kg)', 'Housekeeping', 'bags', 7, 3, 18000, 'housekeeping', 2],
            ['Cooking Gas (50kg)', 'Utilities', 'cylinders', 4, 2, 55000, 'kitchen', 3],
            ['Napkins (pack)', 'Restaurant', 'packs', 40, 15, 3500, 'main_store', 3],
        ];

        foreach ($inventory as $i) {
            $item = InventoryItem::create([
                'name' => $i[0], 'sku' => 'SKU-' . strtoupper(Str::random(6)),
                'category' => $i[1], 'unit' => $i[2], 'quantity' => $i[3],
                'reorder_level' => $i[4], 'cost_price' => $i[5],
                'location' => $i[6], 'supplier_id' => $suppliers[$i[7]]->id,
            ]);

            StockMovement::create([
                'inventory_item_id' => $item->id, 'type' => 'in', 'quantity' => $i[3],
                'to_location' => $i[6], 'reference' => 'Opening stock', 'user_id' => $staff['storekeeper']->id,
            ]);
        }

        // ------------------------------------------------ Purchase orders
        $po1 = PurchaseOrder::create([
            'code' => 'PO-' . strtoupper(Str::random(6)), 'supplier_id' => $suppliers[0]->id,
            'status' => 'pending_approval', 'order_date' => $today,
            'expected_date' => $today->copy()->addDays(3),
            'subtotal' => 425000, 'total' => 425000,
            'created_by' => $staff['procurement']->id,
            'notes' => 'Weekly food restock',
        ]);
        $po1->items()->createMany([
            ['description' => 'Rice (50kg bag)', 'qty' => 5, 'unit_price' => 85000, 'total' => 425000, 'inventory_item_id' => InventoryItem::where('name', 'like', 'Rice%')->value('id')],
        ]);

        $po2 = PurchaseOrder::create([
            'code' => 'PO-' . strtoupper(Str::random(6)), 'supplier_id' => $suppliers[1]->id,
            'status' => 'received', 'order_date' => $today->copy()->subDays(6),
            'expected_date' => $today->copy()->subDays(3), 'received_date' => $today->copy()->subDays(3),
            'subtotal' => 300000, 'total' => 300000,
            'created_by' => $staff['procurement']->id, 'approved_by' => $staff['manager']->id,
        ]);
        $po2->items()->createMany([
            ['description' => 'Local Lager (crate)', 'qty' => 10, 'unit_price' => 15000, 'total' => 150000, 'received_qty' => 10],
            ['description' => 'Red Wine (bottle)', 'qty' => 12, 'unit_price' => 12500, 'total' => 150000, 'received_qty' => 12],
        ]);

        // ------------------------------------------------ Expenses
        foreach ([
            ['Utilities', 'PHCN electricity bill', 185000, 5, 'paid'],
            ['Fuel & Generator', 'Diesel top-up (1,000L)', 950000, 4, 'approved'],
            ['Maintenance', 'AC servicing — floors 2 & 3', 120000, 3, 'approved'],
            ['Linen & Laundry', 'External laundry contract', 85000, 8, 'paid'],
            ['Marketing', 'Social media promotion', 60000, 2, 'pending'],
            ['Miscellaneous', 'Staff welfare', 45000, 1, 'pending'],
        ] as $e) {
            Expense::create([
                'code' => 'EXP-' . strtoupper(Str::random(6)),
                'category' => $e[0], 'description' => $e[1], 'amount' => $e[2],
                'expense_date' => $today->copy()->subDays($e[3]),
                'payment_method' => 'transfer', 'status' => $e[4],
                'recorded_by' => $staff['accountant']->id,
                'approved_by' => in_array($e[4], ['approved', 'paid']) ? $staff['manager']->id : null,
            ]);
        }

        // ------------------------------------------------ Orders & payments (14-day history)
        $foodItems = MenuItem::where('type', 'food')->get();
        $drinkItems = MenuItem::where('type', 'drink')->get();

        foreach (range(0, 13) as $daysAgo) {
            $day = $today->copy()->subDays($daysAgo);
            $numOrders = rand(2, 5);

            foreach (range(1, $numOrders) as $n) {
                $isOpen = $daysAgo === 0 && $n <= 2;
                $picks = $foodItems->random(rand(1, 3))->concat($drinkItems->random(rand(1, 2)));

                $subtotal = 0;
                $lines = [];

                foreach ($picks as $pick) {
                    $qty = rand(1, 3);
                    $subtotal += $qty * (float) $pick->price;
                    $lines[] = [
                        'menu_item_id' => $pick->id, 'name' => $pick->name, 'qty' => $qty,
                        'price' => $pick->price, 'total' => $qty * (float) $pick->price,
                        'station' => $pick->station,
                        'status' => $isOpen ? (rand(0, 1) ? 'pending' : 'preparing') : 'served',
                    ];
                }

                $tax = round($subtotal * 0.075, 2);
                $customer = rand(0, 2) ? $customers->random() : null;
                $placedAt = $day->copy()->setTime(rand(9, 21), rand(0, 59));

                $order = Order::create([
                    'code' => 'ORD-' . strtoupper(Str::random(6)),
                    'customer_id' => $customer?->id,
                    'customer_name' => $customer?->name ?? 'Walk-in Guest',
                    'user_id' => $staff['waiter']->id,
                    'type' => collect(['dine_in', 'dine_in', 'room_service', 'takeaway'])->random(),
                    'location' => 'Table ' . rand(1, 15),
                    'status' => $isOpen ? 'preparing' : 'completed',
                    'payment_status' => $isOpen ? 'unpaid' : 'paid',
                    'subtotal' => $subtotal, 'tax' => $tax, 'total' => $subtotal + $tax,
                    'paid_amount' => $isOpen ? 0 : $subtotal + $tax,
                    'payment_method' => $isOpen ? null : collect(['cash', 'card', 'pos', 'transfer'])->random(),
                    'placed_at' => $placedAt,
                    'created_at' => $placedAt,
                ]);

                $order->items()->createMany($lines);

                if (! $isOpen) {
                    Payment::create([
                        'code' => 'PAY-' . strtoupper(Str::random(6)),
                        'payable_type' => 'order', 'payable_id' => $order->id,
                        'customer_id' => $order->customer_id,
                        'amount' => $order->total, 'method' => $order->payment_method,
                        'received_by' => $staff['waiter']->id,
                        'paid_at' => $placedAt->copy()->addMinutes(50),
                        'created_at' => $placedAt,
                    ]);
                }
            }
        }

        // Booking payments feed the revenue chart too
        foreach (Booking::where('paid_amount', '>', 0)->get() as $booking) {
            Payment::create([
                'code' => 'PAY-' . strtoupper(Str::random(6)),
                'payable_type' => 'booking', 'payable_id' => $booking->id,
                'customer_id' => $booking->customer_id,
                'amount' => $booking->paid_amount, 'method' => 'card',
                'received_by' => $staff['receptionist']->id,
                'paid_at' => Carbon::parse($booking->check_in)->setTime(14, 30),
                'created_at' => Carbon::parse($booking->check_in),
            ]);
        }

        // ------------------------------------------------ Membership, referrals & rewards
        $plans = collect([
            ['Silver', 150000, 5, 1, '#94a3b8', ['5% discount on rooms & dining', 'Priority reservations', 'Birthday treat']],
            ['Gold', 350000, 10, 1.5, '#f59e0b', ['10% discount on rooms & dining', 'Late checkout (2pm)', 'Quarterly spa voucher', 'Priority reservations']],
            ['Platinum', 750000, 15, 2, '#8b5cf6', ['15% discount everywhere', 'Free airport pickup', 'Executive lounge access', 'Dedicated concierge', 'Annual free night']],
        ])->map(fn ($p) => MembershipPlan::create([
            'name' => $p[0], 'slug' => Str::slug($p[0]), 'price' => $p[1],
            'discount_percent' => $p[2], 'points_multiplier' => $p[3], 'color' => $p[4],
            'perks' => $p[5], 'duration_days' => 365,
            'description' => $p[0] . ' tier membership of Epelcon Hospitality.',
        ]));

        foreach ([[0, 1], [1, 2]] as [$custIdx, $planIdx]) {
            $m = Membership::create([
                'code' => 'MEM-' . strtoupper(Str::random(6)),
                'customer_id' => $customers[$custIdx]->id,
                'membership_plan_id' => $plans[$planIdx]->id,
                'starts_at' => $today->copy()->subMonths(2),
                'expires_at' => $today->copy()->addMonths(10),
                'status' => 'active',
            ]);

            Payment::create([
                'code' => 'PAY-' . strtoupper(Str::random(6)),
                'payable_type' => 'membership', 'payable_id' => $m->id,
                'customer_id' => $m->customer_id, 'amount' => $plans[$planIdx]->price,
                'method' => 'transfer', 'received_by' => $staff['receptionist']->id,
                'paid_at' => $today->copy()->subMonths(2)->setTime(12, 0),
                'created_at' => $today->copy()->subMonths(2),
            ]);
        }

        Referral::create([
            'referrer_customer_id' => $customers[0]->id,
            'referred_customer_id' => $customers[2]->id,
            'code_used' => 'EPELCON1', 'reward_points' => 50, 'status' => 'rewarded',
        ]);

        $customers[0]->update(['reward_points' => 185]);
        RewardTransaction::insert([
            ['hotel_id' => $flagship->id, 'customer_id' => $customers[0]->id, 'points' => 50, 'type' => 'referral', 'description' => 'Referred John Adewale', 'created_at' => now()->subDays(9), 'updated_at' => now()->subDays(9)],
            ['hotel_id' => $flagship->id, 'customer_id' => $customers[0]->id, 'points' => 135, 'type' => 'earn', 'description' => 'Stay & dining rewards', 'created_at' => now()->subDays(4), 'updated_at' => now()->subDays(4)],
        ]);
        $demoUser->update(['reward_points' => 185]);

        // ------------------------------------------------ Vendor marketplace
        // Module seeders (HR, guest services, promos, blog, room inspections, messaging)
        foreach ([
            \Database\Seeders\HrSeeder::class,
            \Database\Seeders\ServicesSeeder::class,
            \Database\Seeders\ExtrasSeeder::class,
            \Database\Seeders\BlogSeeder::class,
            \Database\Seeders\RoomInspectionSeeder::class,
            \Database\Seeders\MessagingSeeder::class,
            \Database\Seeders\KitchenStockSeeder::class,
            \Database\Seeders\VendorSpacesSeeder::class,
            \Database\Seeders\CateringSeeder::class,
            \Database\Seeders\HousekeepingTimingSeeder::class,
        ] as $seederClass) {
            if (class_exists($seederClass)) {
                $this->call($seederClass);
                \App\Support\Tenancy::set($flagship); // module seeders may reset tenancy
            }
        }

        foreach ([
            ['Lagos Continental Suites', 'hotel', 'Lagos', 4.6, 240, 'approved'],
            ['Savannah Grand Hotel', 'hotel', 'Abuja', 4.4, 180, 'approved'],
            ['Calabar Marina Resort', 'hotel', 'Calabar', 4.7, 95, 'approved'],
            ['Jos Highland Lodge', 'hotel', 'Jos', 4.2, 60, 'approved'],
            ['Enugu Coal City Hotel', 'hotel', 'Enugu', 4.0, 110, 'pending'],
        ] as $v) {
            Vendor::create([
                'name' => $v[0], 'slug' => Str::slug($v[0]), 'type' => $v[1],
                'city' => $v[2], 'country' => 'Nigeria', 'rating' => $v[3],
                'rooms_count' => $v[4], 'status' => $v[5],
                'commission_percent' => 10,
                'joined_at' => $v[5] === 'approved' ? now()->subMonths(rand(1, 12)) : null,
                'email' => Str::slug($v[0]) . '@example.com',
                'phone' => '+234 70' . rand(10000000, 99999999),
                'description' => 'Partner property on the Epelcon vendor marketplace.',
            ]);
        }
    }
}
