<?php

namespace Database\Seeders;

use App\Models\User;
use App\Models\Customer;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Payment;
use App\Models\Product;
use App\Models\Material;
use Carbon\Carbon;
use Illuminate\Database\Seeder;

class OrderDataSeeder extends Seeder
{
    private array $customers = [];
    private array $products = [];
    private array $materials = [];
    private array $users = [];
    private array $dailyOrderCount = [];

    // Realistic Indonesian business names
    private array $customerNames = [
        'CV Maju Bersama', 'PT Sejahtera Abadi', 'Toko Berkah Jaya', 'UD Sinar Mas',
        'PT Digital Nusantara', 'CV Karya Mandiri', 'Apotek Sehat Selalu', 'Rumah Makan Padang Sederhana',
        'Salon Cantik Jelita', 'Bengkel Motor Jaya', 'Warung Kopi Mantap', 'Toko Bangunan Makmur',
        'CV Printing Express', 'PT Media Kreatif', 'Butik Fashion Trendy', 'Resto Seafood Bahari',
        'Klinik Gigi Senyum', 'Rental Mobil Prima', 'Laundry Bersih Wangi', 'Toko Elektronik Murah',
        'Bakso Pak Kumis', 'Martabak Manis Haji', 'Ayam Geprek Sambal', 'Kue Lapis Legit',
        'Studio Foto Kenangan', 'Percetakan Cepat Kilat', 'Toko Bunga Segar', 'Salon Kecantikan Ayu',
        'Gudang Sembako Murni', 'Distributor Minuman Segar', 'Event Organizer Pro', 'Wedding Planner Elite',
        'Catering Nikmat Rasa', 'Travel Wisata Nusantara', 'Hotel Melati Indah', 'Kost Nyaman Asri',
        'Kantor Akuntan Publik', 'Notaris dan PPAT', 'Konsultan Hukum Prima', 'Bimbel Prestasi',
        'PT Mitra Sejati', 'CV Abadi Jaya', 'Toko Roti Hangat', 'UD Mawar Indah',
        'Gym Fitness Center', 'Spa Relaxation', 'Pet Shop Lucu', 'Optik Jelas Terang',
    ];

    private array $fileNames = [
        'banner_promo_januari', 'spanduk_grand_opening', 'backdrop_acara_kantor', 'neon_box_toko_baru',
        'sticker_branding_motor', 'poster_event_musik', 'brosur_produk_baru', 'kartu_nama_perusahaan',
        'undangan_pernikahan_mewah', 'roll_up_pameran_dagang', 'x_banner_promosi_diskon', 'billboard_jalan_raya',
        'signage_toko_modern', 'menu_board_restoran', 'label_produk_makanan', 'packaging_box_premium',
        'banner_diskon_50persen', 'spanduk_tahun_baru', 'backdrop_ultah_anak', 'banner_imlek_2026',
        'poster_workshop', 'brosur_sekolah_2026', 'banner_valentine', 'spanduk_hut_perusahaan',
        'sticker_motor_racing', 'wallpaper_kantor', 'canvas_foto_keluarga', 'backdrop_photobooth',
    ];

    private array $finishingNotes = [
        null, null, null, null, // More likely no finishing notes
        'Laminasi glossy', 'Laminasi doff', 'Pond/cutting', 'Lipat 2', 'Lipat 3',
        'Mata ayam 4 sudut', 'Selongsong atas bawah', 'Perekat/lem', 'Jahit pinggir',
        'Tali tambahan', 'Lubang gantungan', 'Finishing UV spot', 'Emboss logo',
        'Staples tengah', 'Spiral plastik', 'Hard cover', 'Laminating + pond',
        'Cutting custom shape', 'Lubang mata ayam 6 titik',
    ];

    public function run(): void
    {
        $this->command->info('🚀 Memulai seeding data order (1 Jan - 9 Feb 2026)...');
        
        $this->loadExistingData();
        $this->ensureCustomers();
        $this->enableTrackClicks();
        $this->generateOrders();
        
        $this->command->info('✅ Seeding order selesai!');
    }

    private function loadExistingData(): void
    {
        $this->users = [
            'designer' => User::where('role', User::ROLE_DESIGNER)->first(),
            'kasir' => User::where('role', User::ROLE_KASIR)->first(),
            'operator' => User::where('role', User::ROLE_OPERATOR)->first(),
            'developer' => User::where('role', User::ROLE_DEVELOPER)->first(),
        ];
        
        $this->products = Product::where('is_active', true)->get()->toArray();
        $this->materials = Material::where('is_active', true)->get()->toArray();
        $this->customers = Customer::all()->toArray();
        
        $this->command->info("  📦 Loaded: " . count($this->products) . " products, " . count($this->materials) . " materials, " . count($this->customers) . " customers");
    }

    private function ensureCustomers(): void
    {
        $targetCount = 48;
        $currentCount = count($this->customers);
        
        if ($currentCount < $targetCount) {
            $this->command->info("  👥 Creating " . ($targetCount - $currentCount) . " customers...");
            
            $phonePrefixes = ['0812', '0813', '0857', '0858', '0878', '0877', '0821', '0822', '0852', '0853'];
            $streets = ['Jl. Sudirman', 'Jl. Gatot Subroto', 'Jl. Merdeka', 'Jl. Ahmad Yani', 'Jl. Diponegoro', 'Jl. Imam Bonjol', 'Jl. Thamrin', 'Jl. Kusuma Bangsa'];
            
            for ($i = $currentCount; $i < $targetCount; $i++) {
                $name = $this->customerNames[$i % count($this->customerNames)];
                if ($i >= count($this->customerNames)) {
                    $name .= ' ' . ($i - count($this->customerNames) + 2);
                }
                
                $customer = Customer::create([
                    'name' => $name,
                    'phone' => $phonePrefixes[array_rand($phonePrefixes)] . rand(10000000, 99999999),
                    'email' => strtolower(str_replace([' ', '.'], ['_', ''], $name)) . '@example.com',
                    'address' => $streets[array_rand($streets)] . ' No. ' . rand(1, 200) . ', Jakarta',
                ]);
                
                $this->customers[] = $customer->toArray();
            }
        }
    }

    private function enableTrackClicks(): void
    {
        $productCount = ceil(count($this->products) * 0.4);
        Product::query()->inRandomOrder()->limit($productCount)->update(['track_clicks' => true]);
        
        $materialCount = ceil(count($this->materials) * 0.4);
        Material::query()->inRandomOrder()->limit($materialCount)->update(['track_clicks' => true]);
        
        $this->command->info("  📊 Enabled track_clicks for {$productCount} products and {$materialCount} materials");
    }

    private function generateOrders(): void
    {
        // Period: 1 January 2026 - 9 February 2026
        $startDate = Carbon::create(2026, 1, 1);
        $endDate = Carbon::create(2026, 2, 9);
        $referenceDate = Carbon::create(2026, 2, 9, 23, 59, 59);
        
        $totalOrders = 0;
        $totalCredit = 0;
        $totalPartial = 0;
        $currentDate = $startDate->copy();
        
        while ($currentDate <= $endDate) {
            $isWeekend = $currentDate->isWeekend();
            // Weekday: 4-10 orders, Weekend: 2-6 orders
            $ordersToday = $isWeekend ? rand(2, 6) : rand(4, 10);
            
            // Seasonal boost: first week of January (New Year promo), early Feb (pre-Valentine)
            if ($currentDate->day <= 7 && $currentDate->month == 1) {
                $ordersToday = (int) ($ordersToday * 1.3); // New Year promo
            }
            if ($currentDate->month == 2 && $currentDate->day <= 9) {
                $ordersToday = (int) ($ordersToday * 1.2); // Pre-Valentine
            }
            
            $dateKey = $currentDate->format('Ymd');
            $existingCount = Order::whereDate('created_at', $currentDate)->count();
            $this->dailyOrderCount[$dateKey] = $existingCount;
            
            for ($i = 0; $i < $ordersToday; $i++) {
                $this->dailyOrderCount[$dateKey]++;
                $result = $this->createOrder($currentDate, $this->dailyOrderCount[$dateKey], $referenceDate);
                $totalOrders++;
                if ($result['is_credit']) $totalCredit++;
                if ($result['is_partial']) $totalPartial++;
            }
            
            $currentDate->addDay();
            
            if ($currentDate->day == 1 || $currentDate->gt($endDate)) {
                $this->command->info("  📅 Processed " . $currentDate->copy()->subDay()->format('d M Y') . " - Orders: {$totalOrders}");
            }
        }
        
        $this->command->info("  📊 Total orders: {$totalOrders} | Credit: {$totalCredit} | Partial paid: {$totalPartial}");
    }

    private function createOrder(Carbon $date, int $sequence, Carbon $referenceDate): array
    {
        $customer = $this->customers[array_rand($this->customers)];
        $designer = $this->users['designer'] ?? $this->users['developer'];
        
        $daysSinceOrder = $date->diffInDays($referenceDate);
        
        // Determine credit and payment status
        $isCredit = rand(1, 100) <= 15; // 15% are credit orders
        $isPartial = false;
        
        if ($daysSinceOrder <= 3) {
            // Very recent: mix of statuses
            $productionStatus = $this->randomStatus(['pending', 'proses_cetak', 'finishing', 'selesai']);
            if ($isCredit) {
                $paymentStatus = rand(0, 2) == 0 ? 'partial' : 'unpaid';
                $isPartial = $paymentStatus === 'partial';
            } else {
                $paymentStatus = rand(0, 1) ? 'paid' : 'unpaid';
            }
        } elseif ($daysSinceOrder <= 10) {
            // Recent: mostly in progress or done
            $productionStatus = $this->randomStatus(['proses_cetak', 'finishing', 'selesai']);
            if ($isCredit) {
                $paymentStatus = $this->randomStatus(['unpaid', 'partial', 'paid']);
                $isPartial = $paymentStatus === 'partial';
            } else {
                $paymentStatus = rand(0, 4) > 0 ? 'paid' : 'unpaid'; // 80% paid
            }
        } else {
            // Older: should be completed
            $productionStatus = 'selesai';
            if ($isCredit) {
                $paymentStatus = rand(0, 3) > 0 ? 'paid' : 'partial'; // 75% paid
                $isPartial = $paymentStatus === 'partial';
            } else {
                $paymentStatus = 'paid';
            }
        }
        
        // Business hours: 8am - 6pm
        $hour = rand(8, 18);
        $minute = rand(0, 59);
        $orderTime = $date->copy()->setHour($hour)->setMinute($minute)->setSecond(rand(0, 59));
        
        $invoiceNumber = sprintf('INV-%s-%04d', $date->format('Ymd'), $sequence);
        
        $order = new Order();
        $order->invoice_number = $invoiceNumber;
        $order->customer_id = $customer['id'];
        $order->customer_name = $customer['name'];
        $order->customer_phone = $customer['phone'];
        $order->total_price = 0;
        $order->is_credit = $isCredit;
        $order->payment_status = $paymentStatus;
        $order->production_status = $productionStatus;
        $order->designer_id = $designer->id;
        $order->spk_printed = ($paymentStatus === 'paid') || $isCredit;
        $order->notes = $isCredit ? 'Order piutang - ' . $customer['name'] : null;
        $order->created_at = $orderTime;
        $order->updated_at = $orderTime;
        
        // Set pickup status for completed orders
        if ($productionStatus === 'selesai') {
            $order->pickup_status = rand(0, 3) > 0 ? 'picked_up' : 'not_picked_up';
            if ($order->pickup_status === 'picked_up') {
                $order->picked_up_at = $orderTime->copy()->addHours(rand(4, 72));
            }
        }
        
        if ($order->spk_printed) {
            $order->spk_printed_at = $orderTime->copy()->addMinutes(rand(5, 30));
        }
        
        if (in_array($productionStatus, ['proses_cetak', 'finishing', 'selesai'])) {
            $order->started_at = $orderTime->copy()->addHours(rand(1, 4));
            $order->operator_id = ($this->users['operator'] ?? $designer)->id;
        }
        
        if ($productionStatus === 'selesai') {
            $order->finished_at = $orderTime->copy()->addHours(rand(4, 48));
        }
        
        $order->saveQuietly();
        
        // Create order items (1-4 items per order)
        $itemCount = rand(1, 4);
        $totalPrice = 0;
        
        for ($i = 0; $i < $itemCount; $i++) {
            $item = $this->createOrderItem($order);
            $totalPrice += $item->subtotal;
        }
        
        $order->total_price = $totalPrice;
        
        // Handle payments
        if ($paymentStatus === 'paid') {
            $order->paid_amount = $totalPrice;
            $order->change_amount = 0;
            $order->paid_at = $orderTime->copy()->addMinutes(rand(5, 60));
            $order->cashier_id = ($this->users['kasir'] ?? $designer)->id;
            
            // Create payment record
            $this->createPayment($order, $totalPrice, $orderTime);
            
        } elseif ($paymentStatus === 'partial') {
            // Pay 30-70% of total
            $paidPercent = rand(30, 70) / 100;
            $paidAmount = round($totalPrice * $paidPercent, -3); // Round to thousands
            $order->paid_amount = $paidAmount;
            $order->change_amount = 0;
            
            // Create partial payment(s)
            $numPayments = rand(1, 2);
            $remainingPaid = $paidAmount;
            for ($p = 0; $p < $numPayments && $remainingPaid > 0; $p++) {
                $paymentAmount = $p == $numPayments - 1 ? $remainingPaid : round($remainingPaid * rand(40, 60) / 100, -3);
                $paymentAmount = max($paymentAmount, 10000);
                $this->createPayment($order, min($paymentAmount, $remainingPaid), $orderTime->copy()->addDays($p));
                $remainingPaid -= $paymentAmount;
            }
        }
        
        $order->saveQuietly();
        
        return ['is_credit' => $isCredit, 'is_partial' => $isPartial];
    }

    private function createPayment(Order $order, float $amount, Carbon $date): void
    {
        $methods = ['cash', 'cash', 'cash', 'transfer', 'ewallet']; // More cash payments
        
        Payment::create([
            'order_id' => $order->id,
            'amount' => $amount,
            'payment_method' => $methods[array_rand($methods)],
            'cashier_id' => ($this->users['kasir'] ?? $this->users['developer'])->id,
            'notes' => $order->is_credit ? 'Pembayaran piutang' : null,
            'created_at' => $date,
            'updated_at' => $date,
        ]);
    }

    private function createOrderItem(Order $order): OrderItem
    {
        $product = $this->products[array_rand($this->products)];
        $material = $this->materials[array_rand($this->materials)];
        
        $sizeData = $this->generateSize($material);
        $qty = rand(1, 5);
        
        $basePrice = (float) $material['base_price'];
        $variation = $basePrice * (rand(-5, 10) / 100);
        $basePrice = max(0, $basePrice + $variation);
        
        $sizeValue = $sizeData['value'];
        $calculatedPrice = $basePrice * max(1, $sizeValue);
        $subtotal = $calculatedPrice * $qty;
        
        $fileName = $this->fileNames[array_rand($this->fileNames)] . '_' . rand(100, 999);
        
        $item = new OrderItem();
        $item->order_id = $order->id;
        $item->product_id = $product['id'];
        $item->product_name = $product['name'];
        $item->material_id = $material['id'];
        $item->material_name = $material['name'];
        $item->file_name = $fileName;
        $item->size_description = $sizeData['description'];
        $item->size_value = $sizeValue;
        $item->size_unit = $material['unit'];
        $item->qty = $qty;
        $item->base_price = $basePrice;
        $item->calculated_price = $calculatedPrice;
        $item->subtotal = $subtotal;
        $item->finishing_note = $this->finishingNotes[array_rand($this->finishingNotes)];
        $item->created_at = $order->created_at;
        $item->updated_at = $order->created_at;
        
        $item->saveQuietly();
        
        return $item;
    }

    private function generateSize(array $material): array
    {
        $unit = $material['unit'];
        
        return match ($unit) {
            'm2' => $this->randomFrom([
                ['description' => '1x2 m', 'value' => 2],
                ['description' => '2x3 m', 'value' => 6],
                ['description' => '1.5x3 m', 'value' => 4.5],
                ['description' => '3x5 m', 'value' => 15],
                ['description' => '2x4 m', 'value' => 8],
                ['description' => '1x3 m', 'value' => 3],
                ['description' => '80x120 cm', 'value' => 0.96],
                ['description' => '60x90 cm', 'value' => 0.54],
                ['description' => '4x6 m', 'value' => 24],
                ['description' => '100x150 cm', 'value' => 1.5],
            ]),
            'pcs' => [
                'description' => '1 pcs',
                'value' => 1,
            ],
            'lembar' => $this->randomFrom([
                ['description' => 'A4', 'value' => 1],
                ['description' => 'A3', 'value' => 1],
                ['description' => 'F4', 'value' => 1],
                ['description' => 'A2', 'value' => 1],
            ]),
            'meter' => $this->randomFrom([
                ['description' => '5 meter', 'value' => 5],
                ['description' => '10 meter', 'value' => 10],
                ['description' => '3 meter', 'value' => 3],
                ['description' => '8 meter', 'value' => 8],
            ]),
            default => ['description' => '1', 'value' => 1],
        };
    }

    private function randomFrom(array $options): array
    {
        return $options[array_rand($options)];
    }

    private function randomStatus(array $statuses): string
    {
        return $statuses[array_rand($statuses)];
    }
}
