<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Items;
use App\Models\TypeItems;
use Illuminate\Support\Str;
use Midtrans\Config;
use Midtrans\Snap;
use Illuminate\Support\Facades\Mail;
use App\Mail\OrderReceipt;
use Kreait\Firebase\Factory;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;

class FoodOrder extends Component
{
    public array $cart = [];
    public bool $showCart = false;
    public ?int $typeItemId = null;
    public bool $showEmailInput = false;
    public string $customerEmail = '';
    public bool $isExistingCustomer = false;
    public ?string $selectedTableId = null;
    public ?string $selectedOccupiedTableId = null;
    public string $inputCustomerName = '';
    public bool $showCustomerNameInput = false;
    public bool $isCustomerNameInputDisabled = false;
    public array $availableTables = [];
    public array $occupiedTables = [];
    public Collection $allTablesData;
    public bool $showMapModal = false;
    public ?string $tableIdFromUrl = null;

    private array $lastFirebaseDataHash = [];

    protected array $rules = [
        'customerEmail' => 'required|email|max:255',
        'selectedTableId' => 'nullable|string',
        'selectedOccupiedTableId' => 'nullable|string',
        'inputCustomerName' => 'nullable|string|max:255',
    ];

    protected $listeners = [
        'paymentSuccess' => 'handlePaymentSuccess',
        'tableStatusUpdated' => 'syncTablesFromFirebase',
    ];

    public function mount($typeSlug = null)
    {
        $this->cart = session()->get('cart', []);
        $this->allTablesData = collect();
        $this->syncTablesFromFirebase();

        $this->tableIdFromUrl = request()->query('table_id');
        $type = $typeSlug
            ? TypeItems::whereRaw('LOWER(REPLACE(name, " ", "-")) = ?', [Str::lower($typeSlug)])->first()
            : TypeItems::whereRaw('LOWER(REPLACE(name, " ", "-")) = ?', ['makanan'])->first();

        $this->typeItemId = $type->id ?? null;
    }

    private function getFirebaseDatabase()
    {
        try {
            $path = config('services.firebase.credentials');
            $path = file_exists($path) ? $path : storage_path('app/' . $path);
            throw_unless(file_exists($path), new \Exception("Firebase credentials not found at: $path"));

            return (new Factory)
                ->withServiceAccount($path)
                ->withDatabaseUri(config('services.firebase.database_url'))
                ->createDatabase();
        } catch (\Exception $e) {
            logger()->error("Firebase init failed: " . $e->getMessage());
            $this->dispatch('notify', message: 'Gagal koneksi Firebase: ' . $e->getMessage());
            return null;
        }
    }

        public function syncTablesFromFirebase()
    {
        $db = $this->getFirebaseDatabase();
        if (!$db) return $this->resetTables();

        try {
            $data = $db->getReference('/')->getValue();
            if (!$data) return $this->resetTables();

            $currentHash = md5(json_encode($data));
            if ($this->lastFirebaseDataHash['tables'] ?? null === $currentHash) {
                return; // Tidak berubah, jangan update properti
            }
            $this->lastFirebaseDataHash['tables'] = $currentHash;

            $available = $occupied = $all = [];

            foreach ($data as $id => $d) {
                $isActive = $d['sensors']['table_activation_sensor_active'] ?? 0;
                $reservedBy = $d['reserved_by'] ?? null;
                $table = [
                    'id' => $id,
                    'device_id' => $d['device_id'] ?? $id,
                    'table_activation_sensor_active' => $isActive,
                    'reserved_by' => $reservedBy,
                    'is_available' => !$isActive,
                    'has_reserved_by' => !empty($reservedBy),
                    'firebase_data' => $d
                ];

                $all[$id] = $table;
                $isActive ? ($reservedBy ? $occupied[] = $table : null) : $available[] = $table;
            }

            $this->availableTables = $available;
            $this->occupiedTables = $occupied;
            $this->allTablesData = collect($all);
            $this->attemptAutoSelectTable();
        } catch (\Exception $e) {
            logger()->error("Sync Firebase failed: " . $e->getMessage());
            $this->dispatch('notify', message: 'Gagal sinkron Firebase: ' . $e->getMessage());
            $this->resetTables();
        }
    }

    private function resetTables()
    {
        $this->availableTables = [];
        $this->occupiedTables = [];
        $this->allTablesData = collect();
    }

    private function attemptAutoSelectTable()
    {
        if (!$this->tableIdFromUrl || $this->allTablesData->isEmpty()) return;

        $table = $this->allTablesData->firstWhere('device_id', $this->tableIdFromUrl);
        if (!$table) return $this->dispatch('notify', message: 'Meja tidak ditemukan.');

        $isActive = $table['firebase_data']['sensors']['table_activation_sensor_active'] ?? 0;
        $reserved = $table['reserved_by'] ?? null;

        if (!$isActive) {
            $this->selectedTableId = $table['id'];
            $this->inputCustomerName = auth()->user()->name ?? 'Guest';
            $this->dispatch('notify', message: 'Meja berhasil dipilih otomatis.');
        } elseif ($reserved) {
            $this->selectedOccupiedTableId = $table['id'];
            $this->inputCustomerName = $reserved;
            $this->isExistingCustomer = true;
            $this->dispatch('notify', message: 'Meja sudah terisi oleh ' . $reserved);
        } else {
            $this->dispatch('notify', message: 'Meja tidak tersedia.');
        }
    }

    public function showMap()
    {
        $this->showMapModal = true;
    }

    public function closeMap()
    {
        $this->showMapModal = false;
    }

    public function updatedSelectedTableId($value)
    {
        // Reset state jika pilihan meja tersedia berubah
        $this->selectedOccupiedTableId = null;
        $this->inputCustomerName = '';
        $this->showCustomerNameInput = false;
        $this->isCustomerNameInputDisabled = false;
        $this->resetErrorBag(['inputCustomerName']);

        if ($value) {
            $this->inputCustomerName = auth()->user()->name ?? 'Guest';
            $this->showCustomerNameInput = true;
            // $this->isCustomerNameInputDisabled tetap false
        }
        logger("Meja kosong dipilih: " . $value);
    }

    public function updatedSelectedOccupiedTableId($value)
    {
        // Reset state jika pilihan meja terreservasi berubah
        $this->selectedTableId = null;
        $this->inputCustomerName = '';
        $this->showCustomerNameInput = false;
        $this->isCustomerNameInputDisabled = false;
        $this->resetErrorBag(['inputCustomerName']);

        if ($value) {
            $selectedTable = $this->allTablesData->get($value); // Menggunakan get() dari Collection
            if ($selectedTable && $selectedTable['has_reserved_by']) {
                $this->inputCustomerName = $selectedTable['reserved_by'];
                $this->showCustomerNameInput = true;
                $this->isCustomerNameInputDisabled = true;
                $this->dispatch('notify', message: 'Nama pemesan otomatis terisi: ' . $selectedTable['reserved_by'] . '.');
            } else {
                $this->inputCustomerName = '';
                $this->showCustomerNameInput = true;
                $this->isCustomerNameInputDisabled = false;
                $this->dispatch('notify', message: 'Meja ini terisi, namun nama pemesan belum terdaftar. Mohon masukkan nama Anda.');
            }
        }
        logger("Meja terisi dipilih: " . $value);
    }

    public function updatedIsExistingCustomer($value)
    {
        $this->selectedTableId = null;
        $this->selectedOccupiedTableId = null;
        $this->inputCustomerName = '';
        $this->showCustomerNameInput = false;
        $this->isCustomerNameInputDisabled = false;
        $this->resetErrorBag(['selectedTableId', 'selectedOccupiedTableId', 'inputCustomerName']);

        if (!$value) { // Jika user TIDAK mencentang "Saya sudah memesan meja" (pemesanan baru)
            $this->inputCustomerName = auth()->user()->name ?? 'Guest';
            $this->showCustomerNameInput = true;
            // $this->isCustomerNameInputDisabled tetap false
        }
    }

    private function validateTableSelection()
    {
        $this->resetErrorBag(['selectedTableId', 'selectedOccupiedTableId', 'inputCustomerName']);

        $selectedTableId = $this->isExistingCustomer ? $this->selectedOccupiedTableId : $this->selectedTableId;
        $errorProperty = $this->isExistingCustomer ? 'selectedOccupiedTableId' : 'selectedTableId';

        if (empty($selectedTableId)) {
            $this->addError($errorProperty, 'Pilih meja Anda.');
            return false;
        }

        $selectedTable = $this->allTablesData->get($selectedTableId);

        if (!$selectedTable) {
            $this->addError($errorProperty, 'Meja yang dipilih tidak valid.');
            return false;
        }

        $isSensorActive = ($selectedTable['firebase_data']['sensors']['table_activation_sensor_active'] ?? 0) === 1;

        if ($this->isExistingCustomer) { // Mengisi meja yang sudah terisi
            if (!$isSensorActive) { // Jika meja dipilih sebagai "terisi" tapi sensornya 0 (tersedia)
                $this->addError($errorProperty, 'Meja yang dipilih sebagai "sudah terisi" ternyata masih tersedia.');
                return false;
            }
            if (!$selectedTable['has_reserved_by']) { // Jika meja terisi tapi tidak ada nama pemesan
                $this->addError($errorProperty, 'Meja ini tidak tersedia untuk penambahan pesanan tanpa nama pemesan yang terdaftar. Pilih meja kosong atau meja terisi lain.');
                return false;
            }
            // Validasi nama pemesan untuk meja terisi
            $this->validateOnly('inputCustomerName', ['inputCustomerName' => 'required|string|max:255'], [
                'inputCustomerName.required' => 'Masukkan nama pemesan yang sesuai dengan meja ini.',
            ]);
            if ($this->getErrorBag()->has('inputCustomerName')) {
                return false;
            }
            if (Str::lower($this->inputCustomerName) !== Str::lower($selectedTable['reserved_by'])) {
                $this->addError('inputCustomerName', 'Nama pemesan tidak cocok dengan data meja ini: "' . $selectedTable['reserved_by'] . '".');
                return false;
            }
        } else { // Mengisi meja yang tersedia
            if ($isSensorActive) { // Jika meja dipilih sebagai "tersedia" tapi sensornya 1 (tidak tersedia)
                $this->addError($errorProperty, 'Meja yang dipilih tidak tersedia.');
                return false;
            }
            // Pastikan nama pemesan tidak kosong saat memilih meja kosong
            $this->validateOnly('inputCustomerName', ['inputCustomerName' => 'required|string|max:255'], [
                'inputCustomerName.required' => 'Nama pemesan wajib diisi untuk meja baru.',
            ]);
            if ($this->getErrorBag()->has('inputCustomerName')) {
                return false;
            }
        }
        return true;
    }


    public function checkout()
    {
        if (!$this->validateTableSelection()) {
            return;
        }
        $this->validate(['customerEmail' => 'required|email']);

        logger("Checkout method called.");
        $cartItems = $this->getCartItemsProperty();

        if (empty($cartItems)) {
            logger("Cart is empty");
            $this->dispatch('notify', message: 'Keranjang kosong');
            return;
        }

        try {
            Config::$serverKey = config('services.midtrans.server_key');
            Config::$isProduction = config('services.midtrans.is_production', false);
            Config::$isSanitized = true;
            Config::$is3ds = true;

            $selectedTableData = $this->getSelectedTableForTransaction();

            $params = [
                'transaction_details' => [
                    'order_id' => 'ORDER-' . time() . '-' . uniqid(),
                    'gross_amount' => $this->getCartTotalProperty(),
                ],
                'customer_details' => [
                    'first_name' => $this->inputCustomerName ?: (auth()->user()->name ?? 'Guest'),
                    'email' => auth()->user()->email ?? $this->customerEmail ?? 'guest@example.com',
                ],
                'item_details' => array_map(function($item) {
                    return [
                        'id' => $item['id'],
                        'price' => $item['price'],
                        'quantity' => $item['qty'],
                        'name' => $item['name'],
                    ];
                }, $cartItems),
                'custom_field1' => 'Firebase Table ID: ' . ($selectedTableData['id'] ?? 'N/A'),
                'custom_field2' => 'Nama Meja: ' . ($selectedTableData['device_id'] ?? 'N/A'),
                'custom_field3' => 'Nama Pemesan: ' . $this->inputCustomerName,
            ];

            $snapToken = Snap::getSnapToken($params);
            $this->dispatch('midtransSnapToken', token: $snapToken);

        } catch (\Exception $e) {
            logger("Midtrans error: " . $e->getMessage());
            logger("Error trace: " . $e->getTraceAsString());
            $this->dispatch('notify', message: 'Gagal memproses pembayaran: ' . $e->getMessage());
        }
    }

    public function sendReceiptEmail()
    {
        if (!$this->validateTableSelection()) {
            return;
        }
        $this->validate(['customerEmail' => 'required|email|max:255']);

        $cartItems = $this->getCartItemsProperty();
        $cartTotal = $this->getCartTotalProperty();
        $mejaDetail = $this->getSelectedTableForTransaction();

        try {
            Mail::to($this->customerEmail)->send(new OrderReceipt($cartItems, $cartTotal, $mejaDetail));

            $this->dispatch('notify', message: 'Detail pesanan telah dikirim ke email Anda.');
            $this->updateTableAndResetState(); // Menggunakan fungsi baru
        } catch (\Exception $e) {
            logger("Failed to send receipt email: " . $e->getMessage());
            $this->dispatch('notify', message: 'Gagal mengirim email. Silakan coba lagi.');
        }
    }

    public function skipPayment()
    {
        if (!$this->validateTableSelection()) {
            return;
        }

        $this->dispatch('notify', message: 'Pesanan Anda telah diproses tanpa pembayaran.');
        $this->updateTableAndResetState(); // Menggunakan fungsi baru
    }

    public function handlePaymentSuccess()
    {
        $this->dispatch('notify', message: 'Pembayaran berhasil!');
        $this->updateTableAndResetState(); // Menggunakan fungsi baru
    }

    // Fungsi Pembantu Baru
    private function getSelectedTableForTransaction(): ?array
    {
        $tableId = $this->selectedTableId ?? $this->selectedOccupiedTableId;
        return $this->allTablesData->get($tableId);
    }

    // Fungsi Pembantu Baru untuk mengupdate meja dan mereset state
    private function updateTableAndResetState()
    {
        $tableData = $this->getSelectedTableForTransaction();
        if ($tableData) {
            $updates = [
                'sensors/table_activation_sensor_active' => 1,
                'reserved_by' => $this->inputCustomerName
            ];
            $this->updateFirebaseTableStatus($tableData['id'], $updates);
        }
        $this->clearCartAndResetState();
    }

    public function updateFirebaseTableStatus(string $firebaseTableId, array $updates, bool $refresh = true)
    {
        $database = $this->getFirebaseDatabase();
        if (!$database) return;

        try {
            $database->getReference($firebaseTableId)->update($updates);
            logger("Firebase: Updated {$firebaseTableId} with " . json_encode($updates));
            $this->dispatch('notify', message: "Status meja '{$firebaseTableId}' berhasil diperbarui di Firebase.");

            if ($refresh) {
                $this->syncTablesFromFirebase();
            }
        } catch (\Exception $e) {
            logger()->error("Failed to update Firebase for table ID {$firebaseTableId}: " . $e->getMessage());
            $this->dispatch('notify', message: 'Gagal memperbarui status meja di Firebase: ' . $e->getMessage());
        }
    }

    private function clearCartAndResetState()
    {
        $this->cart = [];
        session()->forget('cart');
        $this->showCart = false;
        $this->showEmailInput = false;
        $this->customerEmail = '';
        $this->selectedTableId = null;
        $this->selectedOccupiedTableId = null;
        $this->inputCustomerName = '';
        $this->resetValidation();
    }

    public function render()
    {
        return view('livewire.food-order', [
            'foodItems' => $this->getFilteredFoodItemsProperty(),
            'cartItems' => $this->getCartItemsProperty(),
            'cartTotal' => $this->getCartTotalProperty(),
            'pageTitle' => $this->getPageTitleProperty(),
            'typeItemId' => $this->typeItemId,
            'allTypeItems' => $this->getAllTypeItemsProperty(),
            'availableTables' => $this->availableTables,
            'occupiedTables' => $this->occupiedTables,
            'allTablesData' => $this->allTablesData->toArray(), // Kirim sebagai array ke view
            'tableIdFromUrl' => $this->tableIdFromUrl,
        ])->layout('components.layouts.front');
    }

    // --- Helper Properties ---

    public function getFoodItemsProperty()
    {
        return Items::all();
    }

    public function getAllTypeItemsProperty() // Menggabungkan getTypeItemsProperty
    {
        return TypeItems::all();
    }

    public function getFilteredFoodItemsProperty()
    {
        if ($this->typeItemId) {
            return Items::where('type_item_id', $this->typeItemId)->get();
        }
        return Items::all();
    }

    public function getCartItemsProperty()
    {
        $items = [];
        foreach ($this->cart as $itemId => $qty) {
            $item = Items::find($itemId);
            if ($item) {
                $items[] = [
                    'id' => $item->id,
                    'name' => $item->name,
                    'price' => $item->price,
                    'qty' => $qty,
                    'total_price' => $item->price * $qty,
                ];
            }
        }
        return $items;
    }

    public function getCartTotalProperty()
    {
        return collect($this->getCartItemsProperty())->sum('total_price');
    }

    public function getPageTitleProperty()
    {
        if ($this->typeItemId) {
            $type = TypeItems::find($this->typeItemId);
            return $type ? $type->name : 'Semua Menu';
        }
        return 'Semua Menu';
    }

    public function addToCart($itemId)
    {
        $item = Items::find($itemId);
        if (!$item) {
            $this->dispatch('notify', message: 'Item tidak ditemukan.');
            return;
        }

        $this->cart[$itemId] = ($this->cart[$itemId] ?? 0) + 1;
        session()->put('cart', $this->cart);
        $this->dispatch('notify', message: $item->name . ' ditambahkan ke keranjang.');
    }

    public function removeFromCart($itemId)
    {
        if (isset($this->cart[$itemId])) {
            $item = Items::find($itemId); // Get item before potential unset
            if ($this->cart[$itemId] > 1) {
                $this->cart[$itemId]--;
            } else {
                unset($this->cart[$itemId]);
            }
            session()->put('cart', $this->cart);
            $this->dispatch('notify', message: $item->name . ' dihapus dari keranjang.');
            if (empty($this->cart)) {
                $this->showCart = false;
            }
        }
    }

    public function openCart()
    {
        $this->showCart = true;
    }

    public function closeCart()
    {
        $this->showCart = false;
    }

    public function filterByType($typeId)
    {
        $this->typeItemId = $typeId;
        $type = TypeItems::find($typeId);
        if ($type) {
            $typeSlug = Str::slug($type->name);
            $newUrl = route('menu.byType', ['typeSlug' => $typeSlug], false);
            $this->dispatch('updateUrl', url: $newUrl);
        }
    }
}
