<?php

namespace App\Livewire\Admin\Pesanan;

use App\Enums\OrderStatus;
use App\Enums\PaymentMethod;
use App\Enums\PaymentStatus;
use App\Models\Order;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
use Livewire\WithPagination;

#[Layout('layouts.admin')]
#[Title('Pesanan')]
class Index extends Component
{
    use WithPagination;

    // ── Search & Filter ─────────────────────────────────────────────────
    public string $search          = '';
    public string $filterTanggal   = '';
    public string $filterStatus    = '';
    public string $filterPembayaran = '';
    public string $filterCustomer  = '';

    // ── Sorting ──────────────────────────────────────────────────────────
    public string $sortBy        = 'created_at';
    public string $sortDirection = 'desc';

    // ── Pagination ───────────────────────────────────────────────────────
    public int $perPage = 25;

    // ── Modal Ubah Status ────────────────────────────────────────────────
    public bool $showStatusModal = false;
    public ?int $statusOrderId   = null;
    public string $newStatus     = '';
    public string $statusNote    = '';
    public array $availableStatuses = [];

    // ── Modal Batalkan ───────────────────────────────────────────────────
    public bool $showCancelModal = false;
    public ?int $cancelOrderId   = null;
    public string $cancelReason  = '';

    public function updatingSearch(): void           { $this->resetPage(); }
    public function updatingFilterTanggal(): void    { $this->resetPage(); }
    public function updatingFilterStatus(): void     { $this->resetPage(); }
    public function updatingFilterPembayaran(): void { $this->resetPage(); }
    public function updatingFilterCustomer(): void   { $this->resetPage(); }
    public function updatingPerPage(): void          { $this->resetPage(); }

    public function sortBy(string $column): void
    {
        if ($this->sortBy === $column) {
            $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sortBy        = $column;
            $this->sortDirection = 'asc';
        }
    }

    public function resetFilters(): void
    {
        $this->reset([
            'search', 'filterTanggal', 'filterStatus',
            'filterPembayaran', 'filterCustomer',
        ]);
        $this->resetPage();
    }

    // ── Ubah Status ──────────────────────────────────────────────────────

    public function openStatusModal(int $orderId): void
    {
        $order = Order::with('payment')->findOrFail($orderId);

        $isCod           = $order->payment_method === PaymentMethod::Cod;
        $paymentVerified = $order->payment?->status === PaymentStatus::Verified;
        $operationalStatuses = [OrderStatus::Processing, OrderStatus::Delivering, OrderStatus::Completed];

        // BFS v1.1 Phase C — bangun daftar status yang boleh ditampilkan di dropdown.
        // Rule-1: paid tidak pernah ditampilkan (hanya dari verifyPayment()).
        // Rule-2/3: processing/delivering/completed disembunyikan jika payment belum verified (non-COD).
        // Rule-4: COD dikecualikan — boleh pilih operasional tanpa cek payment.
        $this->availableStatuses = array_values(array_filter(
            $order->status->allowedTransitions(),
            function (OrderStatus $next) use ($isCod, $paymentVerified, $operationalStatuses) {
                if ($next === OrderStatus::Paid) {
                    return false;
                }
                if (in_array($next, $operationalStatuses) && ! $isCod && ! $paymentVerified) {
                    return false;
                }
                return true;
            }
        ));

        $this->statusOrderId   = $order->id;
        $this->newStatus       = '';
        $this->statusNote      = '';
        $this->showStatusModal = true;
    }

    public function updateStatus(): void
    {
        abort_unless(Auth::user()->can('order.update-status'), 403);

        $this->validate([
            'newStatus' => ['required', 'string'],
        ]);

        $order   = Order::with('payment')->findOrFail($this->statusOrderId);
        $current = $order->status;
        $target  = OrderStatus::from($this->newStatus);

        if (! $current->canTransitionTo($target)) {
            $this->addError('newStatus', 'Transisi status dari "' . $current->label() . '" ke "' . $target->label() . '" tidak diizinkan.');
            return;
        }

        // BFS v1.1 Phase B — Rule-1: blok perubahan ke 'paid' dari Menu Pesanan.
        // Status paid hanya boleh berasal dari verifyPayment() di Menu Pembayaran.
        if ($target === OrderStatus::Paid) {
            $this->addError('newStatus', 'Status "Sudah Dibayar" hanya dapat diberikan melalui proses verifikasi pembayaran di Menu Pembayaran.');
            return;
        }

        // BFS v1.1 Phase B — Rule-2 & Rule-3: validasi status payment sebelum operasional.
        // Khusus untuk target processing/delivering/completed pada order NON-COD.
        // COD dikecualikan karena pembayaran diterima saat serah terima (BFS v1.1 Revisi R-1).
        $operationalStatuses = [OrderStatus::Processing, OrderStatus::Delivering, OrderStatus::Completed];
        if (in_array($target, $operationalStatuses) && $order->payment_method !== PaymentMethod::Cod) {
            $payment = $order->payment;

            if (! $payment || $payment->status === PaymentStatus::Pending) {
                $this->addError('newStatus', 'Pesanan tidak dapat diproses karena pembayaran belum diverifikasi.');
                return;
            }

            if ($payment->status === PaymentStatus::Rejected) {
                $this->addError('newStatus', 'Pesanan tidak dapat diproses karena pembayaran telah ditolak. Minta customer mengupload ulang bukti pembayaran.');
                return;
            }
        }

        $order->update([
            'status'      => $target->value,
            'admin_notes' => $this->statusNote
                ? trim(($order->admin_notes ? $order->admin_notes . "\n" : '') . $this->statusNote)
                : $order->admin_notes,
        ]);

        $this->showStatusModal = false;
        $this->dispatch('notify', type: 'success', message: 'Status pesanan berhasil diubah menjadi "' . $target->label() . '".');
    }

    // ── Batalkan Pesanan ─────────────────────────────────────────────────

    public function openCancelModal(int $orderId): void
    {
        $this->cancelOrderId   = $orderId;
        $this->cancelReason    = '';
        $this->showCancelModal = true;
    }

    public function cancelOrder(): void
    {
        abort_unless(Auth::user()->can('order.cancel'), 403);

        $order = Order::findOrFail($this->cancelOrderId);

        if (! $order->isCancellable()) {
            $this->addError('cancelReason', 'Pesanan dengan status "' . $order->status->label() . '" tidak dapat dibatalkan.');
            return;
        }

        $order->update([
            'status'      => OrderStatus::Cancelled->value,
            'admin_notes' => trim(($order->admin_notes ? $order->admin_notes . "\n" : '') . 'Dibatalkan: ' . $this->cancelReason),
        ]);

        $this->showCancelModal = false;
        $this->dispatch('notify', type: 'success', message: 'Pesanan berhasil dibatalkan.');
    }

    public function render()
    {
        $orders = Order::query()
            ->with(['items', 'payment', 'deliveryArea'])
            ->when($this->search, function ($q) {
                $q->where(function ($q) {
                    $q->where('order_number', 'like', "%{$this->search}%")
                      ->orWhere('customer_name', 'like', "%{$this->search}%")
                      ->orWhere('customer_phone', 'like', "%{$this->search}%");
                });
            })
            ->when($this->filterTanggal, fn ($q) =>
                $q->whereDate('created_at', $this->filterTanggal))
            ->when($this->filterStatus, fn ($q) =>
                $q->where('status', $this->filterStatus))
            ->when($this->filterPembayaran, function ($q) {
                if ($this->filterPembayaran === 'unpaid') {
                    $q->whereDoesntHave('payment');
                } else {
                    $q->whereHas('payment', fn ($q) =>
                        $q->where('status', $this->filterPembayaran));
                }
            })
            ->when($this->filterCustomer, fn ($q) =>
                $q->where('customer_name', 'like', "%{$this->filterCustomer}%"))
            ->when($this->sortBy === 'customer', function ($q) {
                $q->orderBy('customer_name', $this->sortDirection);
            }, function ($q) {
                $q->orderBy($this->sortBy, $this->sortDirection);
            })
            ->paginate($this->perPage);

        $statusOptions  = OrderStatus::cases();
        $paymentOptions = PaymentStatus::cases();

        return view('livewire.admin.pesanan.index', compact(
            'orders', 'statusOptions', 'paymentOptions'
        ));
    }
}
