<?php

declare(strict_types=1);

namespace Database\Seeders;

use App\Models\Outlet;
use App\Models\Ingredient;
use App\Models\Table;
use App\Models\Customer;
use App\Models\Modifier;
use App\Models\Promo;
use App\Models\StockOpname;
use App\Models\StockOpnameItem;
use App\Models\Waste;
use App\Models\StockTransaction;
use App\Models\Product;
use App\Models\User;
use App\Models\Supplier;
use App\Models\Transaction;
use App\Models\TransactionItem;
use App\Models\Reservation;
use Illuminate\Database\Seeder;

class CompletePhasesSeeder extends Seeder
{
    public function run(): void
    {
        // Truncate tables to prevent duplicate entries if seeder is run multiple times
        \Illuminate\Support\Facades\Schema::disableForeignKeyConstraints();
        StockOpname::truncate();
        StockOpnameItem::truncate();
        Waste::truncate();
        StockTransaction::truncate();
        \Illuminate\Support\Facades\Schema::enableForeignKeyConstraints();

        // 1. Update existing Ingredients with conversion ratios & prices
        $beans = Ingredient::where('name', 'like', '%Biji Kopi%')->first();
        if ($beans) {
            $beans->update([
                'purchase_unit' => 'kg',
                'usage_unit' => 'g',
                'conversion_ratio' => 1000.0,
                'purchase_price' => 150000.00, // Rp 150.000 per kg
            ]);
        }

        $milk = Ingredient::where('name', 'like', '%Milk%')->first();
        if ($milk) {
            $milk->update([
                'purchase_unit' => 'carton',
                'usage_unit' => 'ml',
                'conversion_ratio' => 1000.0,
                'purchase_price' => 20000.00, // Rp 20.000 per carton (1L)
            ]);
        }

        $aren = Ingredient::where('name', 'like', '%Aren%')->first();
        if ($aren) {
            $aren->update([
                'purchase_unit' => 'bottle',
                'usage_unit' => 'ml',
                'conversion_ratio' => 1000.0,
                'purchase_price' => 50000.00, // Rp 50.000 per bottle (1L)
            ]);
        }

        // Set other ingredients defaults
        Ingredient::whereNull('purchase_unit')->update([
            'purchase_unit' => 'unit',
            'usage_unit' => 'unit',
            'conversion_ratio' => 1.0,
            'purchase_price' => 5000.00,
        ]);

        // 6. Seed Stock Opnames
        $adminUser = User::role('Admin')->first() ?? User::first();
        $kemangOutlet = Outlet::where('name', 'like', '%Kemang%')->first() ?? Outlet::first();
        $senopatiOutlet = Outlet::where('name', 'like', '%Senopati%')->first() ?? Outlet::latest()->first();

        if ($kemangOutlet && $adminUser) {
            // Completed opname
            $opname1 = StockOpname::create([
                'outlet_id' => $kemangOutlet->id,
                'user_id' => $adminUser->id,
                'status' => 'completed',
                'created_at' => now()->subDays(2),
            ]);

            // Seed items
            $ings = Ingredient::all();
            foreach ($ings as $ing) {
                StockOpnameItem::create([
                    'stock_opname_id' => $opname1->id,
                    'item_type' => 'Ingredient',
                    'item_id' => $ing->id,
                    'system_qty' => 5000,
                    'actual_qty' => 4950,
                    'difference_qty' => -50,
                ]);
            }
        }

        if ($senopatiOutlet && $adminUser) {
            // Draft opname
            $opname2 = StockOpname::create([
                'outlet_id' => $senopatiOutlet->id,
                'user_id' => $adminUser->id,
                'status' => 'draft',
                'created_at' => now()->subHours(4),
            ]);

            $ings = Ingredient::all();
            foreach ($ings as $ing) {
                StockOpnameItem::create([
                    'stock_opname_id' => $opname2->id,
                    'item_type' => 'Ingredient',
                    'item_id' => $ing->id,
                    'system_qty' => 3000,
                    'actual_qty' => 3000,
                    'difference_qty' => 0,
                ]);
            }
        }

        // 7. Seed Wastes (Bahan Rusak / Terbuang)
        if ($kemangOutlet && $adminUser) {
            $milk = Ingredient::where('name', 'like', '%Milk%')->first();
            $beans = Ingredient::where('name', 'like', '%Kopi%')->first();
            $croissant = Product::where('name', 'like', '%Croissant%')->first();

            if ($milk) {
                Waste::create([
                    'outlet_id' => $kemangOutlet->id,
                    'user_id' => $adminUser->id,
                    'item_type' => 'Ingredient',
                    'item_id' => $milk->id,
                    'qty' => 1000.0, // 1000 ml
                    'notes' => 'Susu UHT basi karena pintu kulkas terbuka semalaman.',
                    'created_at' => now()->subDays(1),
                ]);
            }

            if ($beans) {
                Waste::create([
                    'outlet_id' => $kemangOutlet->id,
                    'user_id' => $adminUser->id,
                    'item_type' => 'Ingredient',
                    'item_id' => $beans->id,
                    'qty' => 150.0, // 150g coffee
                    'notes' => 'Biji kopi tumpah saat proses refilling grinder.',
                    'created_at' => now()->subDays(3),
                ]);
            }

            if ($croissant) {
                Waste::create([
                    'outlet_id' => $kemangOutlet->id,
                    'user_id' => $adminUser->id,
                    'item_type' => 'Product',
                    'item_id' => $croissant->id,
                    'qty' => 3.0, // 3 pcs
                    'notes' => 'Croissant gosong saat di-reheat.',
                    'created_at' => now()->subDays(2),
                ]);
            }
        }

        // 8. Seed Stock Transactions (Purchasing / Supply Log)
        if ($kemangOutlet && $adminUser) {
            $supplier = Supplier::first();
            $beans = Ingredient::where('name', 'like', '%Kopi%')->first();
            $cups = Ingredient::where('name', 'like', '%Cup%')->first();

            if ($beans && $supplier) {
                StockTransaction::create([
                    'outlet_id' => $kemangOutlet->id,
                    'user_id' => $adminUser->id,
                    'supplier_id' => $supplier->id,
                    'item_type' => 'Ingredient',
                    'item_id' => $beans->id,
                    'qty' => 10000.0, // 10kg
                    'type' => 'in',
                    'notes' => 'Pembelian biji kopi Espresso Blend bulanan.',
                    'created_at' => now()->subDays(5),
                ]);
            }

            if ($cups && $supplier) {
                StockTransaction::create([
                    'outlet_id' => $kemangOutlet->id,
                    'user_id' => $adminUser->id,
                    'supplier_id' => $supplier->id,
                    'item_type' => 'Ingredient',
                    'item_id' => $cups->id,
                    'qty' => 500.0, // 500 pcs
                    'type' => 'in',
                    'notes' => 'Restock paper cup 12oz.',
                    'created_at' => now()->subDays(5),
                ]);
            }
        }

        // 9. Generate Dummy Transactions for the last 30 days
        $products = Product::all();
        $paymentMethods = ['cash', 'transfer', 'qris'];
        $orderTypes = ['dine_in', 'take_away', 'delivery'];
        $customers = Customer::all();

        // Truncate transactions first to ensure no duplicate IDs
        \Illuminate\Support\Facades\Schema::disableForeignKeyConstraints();
        Transaction::truncate();
        TransactionItem::truncate();
        Reservation::truncate();
        \Illuminate\Support\Facades\Schema::enableForeignKeyConstraints();

        for ($day = 30; $day >= 0; $day--) {
            $date = now()->subDays($day);
            
            // Random transactions per day
            $txnCount = rand(3, 10);
            for ($i = 0; $i < $txnCount; $i++) {
                // Randomize time of transaction
                $hour = rand(8, 21);
                $minute = rand(0, 59);
                $txnTime = $date->copy()->setTime($hour, $minute, 0);

                // Select random outlet
                $outlet = rand(0, 1) === 0 ? $kemangOutlet : $senopatiOutlet;
                if (!$outlet) continue;

                // Pick cashier user
                $cashier = User::where('outlet_id', $outlet->id)->role('Kasir')->first() 
                    ?? User::role('Kasir')->first() 
                    ?? User::first();

                // Select random customer
                $customer = $customers->count() > 0 ? $customers->random() : null;

                // Select order type
                $orderType = $orderTypes[array_rand($orderTypes)];

                // Assign table or queue number
                $tableId = null;
                $queueNumber = null;

                if ($orderType === 'dine_in') {
                    $tablesList = Table::where('outlet_id', $outlet->id)->get();
                    if ($tablesList->count() > 0) {
                        $tableId = $tablesList->random()->id;
                    }
                } else {
                    $queueNumber = 'Q-' . str_pad((string)rand(1, 99), 3, '0', STR_PAD_LEFT);
                }

                // Select 1 to 3 items
                $itemCount = rand(1, 3);
                $subtotal = 0;
                $itemsData = [];

                for ($j = 0; $j < $itemCount; $j++) {
                    if ($products->count() === 0) continue;
                    $prod = $products->random();
                    $qty = rand(1, 2);
                    $variant = $prod->category === 'Coffee' || $prod->category === 'Non-Coffee' ? (rand(0, 1) === 0 ? 'ice' : 'hot') : null;
                    
                    $price = (float)$prod->price;
                    $itemSubtotal = $price * $qty;
                    $subtotal += $itemSubtotal;

                    $itemsData[] = [
                        'product_id' => $prod->id,
                        'qty' => $qty,
                        'variant' => $variant,
                        'price' => $price,
                        'subtotal' => $itemSubtotal,
                    ];
                }

                // Calculations
                $service = ($subtotal * 5) / 100;
                $tax = (($subtotal + $service) * 10) / 100;
                $total = $subtotal + $service + $tax;

                // Unique Transaction Number
                $dateStr = $txnTime->format('Ymd');
                $timeStr = $txnTime->format('His');
                $randStr = rand(1000, 9999);
                $transactionNumber = "TXN-{$outlet->id}-{$dateStr}-{$timeStr}-{$randStr}";

                // Save Transaction
                $transaction = Transaction::create([
                    'transaction_number' => $transactionNumber,
                    'outlet_id' => $outlet->id,
                    'user_id' => $cashier ? $cashier->id : 1,
                    'total_amount' => $total,
                    'tax_amount' => $tax,
                    'service_charge_amount' => $service,
                    'payment_method' => $paymentMethods[array_rand($paymentMethods)],
                    'status' => 'success',
                    'order_type' => $orderType,
                    'table_id' => $tableId,
                    'customer_id' => $customer ? $customer->id : null,
                    'queue_number' => $queueNumber,
                    'created_at' => $txnTime,
                    'updated_at' => $txnTime,
                ]);

                // Save items
                foreach ($itemsData as $it) {
                    $kitchenStatus = 'served';
                    if ($day === 0) {
                        $statuses = ['pending', 'cooking', 'ready', 'served'];
                        $kitchenStatus = $statuses[array_rand($statuses)];
                    }

                    TransactionItem::create([
                        'transaction_id' => $transaction->id,
                        'product_id' => $it['product_id'],
                        'qty' => $it['qty'],
                        'variant' => $it['variant'],
                        'price' => $it['price'],
                        'subtotal' => $it['subtotal'],
                        'kitchen_status' => $kitchenStatus,
                        'created_at' => $txnTime,
                        'updated_at' => $txnTime,
                    ]);
                }
            }
        }

        // 10. Seed Table Reservations (Reservasi Meja)
        if ($kemangOutlet && $customers->count() > 0) {
            $tablesList = Table::where('outlet_id', $kemangOutlet->id)->get();
            $memberCustomers = Customer::where('is_member', true)->get();

            if ($tablesList->count() > 0 && $memberCustomers->count() > 0) {
                // Reservation 1: Pending (future reservation)
                Reservation::create([
                    'customer_id' => $memberCustomers->first()->id,
                    'table_id' => $tablesList->first()->id,
                    'outlet_id' => $kemangOutlet->id,
                    'reservation_date' => now()->addDays(1)->format('Y-m-d'),
                    'reservation_time' => '19:00',
                    'status' => 'pending',
                ]);

                // Reservation 2: Confirmed (future reservation)
                Reservation::create([
                    'customer_id' => $memberCustomers->last()->id,
                    'table_id' => $tablesList->get(1) ? $tablesList->get(1)->id : $tablesList->first()->id,
                    'outlet_id' => $kemangOutlet->id,
                    'reservation_date' => now()->addDays(2)->format('Y-m-d'),
                    'reservation_time' => '15:30',
                    'status' => 'confirmed',
                ]);
            }
        }

        if ($senopatiOutlet && $customers->count() > 0) {
            $tablesList = Table::where('outlet_id', $senopatiOutlet->id)->get();
            $memberCustomers = Customer::where('is_member', true)->get();

            if ($tablesList->count() > 0 && $memberCustomers->count() > 0) {
                // Reservation 3: Completed/Seated (today reservation)
                Reservation::create([
                    'customer_id' => $memberCustomers->first()->id,
                    'table_id' => $tablesList->first()->id,
                    'outlet_id' => $senopatiOutlet->id,
                    'reservation_date' => now()->format('Y-m-d'),
                    'reservation_time' => '12:00',
                    'status' => 'seated',
                ]);
            }
        }
    }
}
