<?php

namespace App\Livewire\Admin\Pembayaran;

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

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

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

    // ── Sorting ───────────────────────────────────────────────────────────
    public string $sortBy = 'newest'; // newest | oldest | highest | lowest

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

    // ── Modal Verifikasi ─────────────────────────────────────────────────
    public bool $showVerifyModal = false;
    public ?int $verifyPaymentId = null;

    // ── Modal Tolak ──────────────────────────────────────────────────────
    public bool $showRejectModal = false;
    public ?int $rejectPaymentId = null;
    public string $rejectReason  = '';

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

    // ── Verifikasi ───────────────────────────────────────────────────────

    public function openVerifyModal(int $paymentId): void
    {
        $payment = Payment::findOrFail($paymentId);

        if (! $payment->isPending()) {
            $this->dispatch('notify', type: 'error', message: 'Hanya pembayaran berstatus "Menunggu Verifikasi" yang dapat diproses.');
            return;
        }

        $this->verifyPaymentId = $payment->id;
        $this->showVerifyModal = true;
    }

    public function verifyPayment(): void
    {
        abort_unless(Auth::user()->can('payment.verify'), 403);

        $payment = Payment::with('order')->findOrFail($this->verifyPaymentId);

        if (! $payment->isPending()) {
            $this->showVerifyModal = false;
            $this->dispatch('notify', type: 'error', message: 'Pembayaran ini sudah diproses sebelumnya.');
            return;
        }

        $payment->update([
            'status'      => PaymentStatus::Verified->value,
            'verified_by' => Auth::id(),
            'verified_at' => now(),
        ]);

        // BFS v1.1 — Sinkronisasi satu arah: Payment Verified → Order Paid
        // Hanya dijalankan jika order masih pending (belum bergerak).
        // Untuk COD: saat verifikasi terjadi, order biasanya sudah di delivering,
        // sehingga kondisi ini tidak terpenuhi dan sinkronisasi tidak berjalan — benar.
        if ($payment->order->isPending()) {
            $payment->order->update(['status' => OrderStatus::Paid->value]);
        }

        $this->showVerifyModal = false;
        $this->dispatch('notify', type: 'success', message: 'Pembayaran berhasil diverifikasi.');
    }

    // ── Tolak ────────────────────────────────────────────────────────────

    public function openRejectModal(int $paymentId): void
    {
        $payment = Payment::findOrFail($paymentId);

        if (! $payment->isPending()) {
            $this->dispatch('notify', type: 'error', message: 'Hanya pembayaran berstatus "Menunggu Verifikasi" yang dapat diproses.');
            return;
        }

        $this->rejectPaymentId = $payment->id;
        $this->rejectReason    = '';
        $this->showRejectModal = true;
    }

    public function rejectPayment(): void
    {
        abort_unless(Auth::user()->can('payment.reject'), 403);

        $this->validate([
            'rejectReason' => ['required', 'string', 'min:5'],
        ], [
            'rejectReason.required' => 'Alasan penolakan wajib diisi.',
            'rejectReason.min'      => 'Alasan penolakan minimal 5 karakter.',
        ]);

        $payment = Payment::with('order')->findOrFail($this->rejectPaymentId);

        if (! $payment->isPending()) {
            $this->showRejectModal = false;
            $this->dispatch('notify', type: 'error', message: 'Pembayaran ini sudah diproses sebelumnya.');
            return;
        }

        // BFS v1.1 — Validasi V-6: tidak boleh reject jika order sudah masuk operasional.
        // Secara bisnis: barang sudah diproses atau sedang dikirim, reject tidak relevan.
        $orderStatus = $payment->order->status;
        if (in_array($orderStatus, [OrderStatus::Processing, OrderStatus::Delivering, OrderStatus::Completed])) {
            $this->showRejectModal = false;
            $this->dispatch('notify', type: 'error', message: 'Pembayaran tidak dapat ditolak. Pesanan sudah masuk tahap operasional (' . $orderStatus->label() . ').');
            return;
        }

        $payment->update([
            'status'           => PaymentStatus::Rejected->value,
            'verified_by'      => Auth::id(),
            'verified_at'      => now(),
            'rejection_notes'  => $this->rejectReason,
        ]);

        // BFS v1.1 — Sinkronisasi satu arah: Payment Rejected → Order kembali Pending
        // Hanya dijalankan jika order masih paid (belum operasional).
        if ($payment->order->status === OrderStatus::Paid) {
            $payment->order->update(['status' => OrderStatus::Pending->value]);
        }

        $this->showRejectModal = false;
        $this->dispatch('notify', type: 'success', message: 'Pembayaran berhasil ditolak.');
    }

    public function render()
    {
        $payments = Payment::query()
            ->with(['order', 'verifiedBy'])
            ->when($this->filterStatus, fn ($q) =>
                $q->where('status', $this->filterStatus))
            ->when($this->search, function ($q) {
                $q->where(function ($q) {
                    $q->whereHas('order', fn ($q) =>
                        $q->where('order_number', 'like', "%{$this->search}%")
                          ->orWhere('customer_name', 'like', "%{$this->search}%")
                      )
                      ->orWhere('id', 'like', "%{$this->search}%");
                });
            })
            ->when($this->sortBy === 'newest',  fn ($q) => $q->orderByDesc('created_at'))
            ->when($this->sortBy === 'oldest',  fn ($q) => $q->orderBy('created_at'))
            ->when($this->sortBy === 'highest', fn ($q) => $q->orderByDesc('amount'))
            ->when($this->sortBy === 'lowest',  fn ($q) => $q->orderBy('amount'))
            ->paginate($this->perPage);

        $statusOptions = PaymentStatus::cases();

        return view('livewire.admin.pembayaran.index', compact('payments', 'statusOptions'));
    }
}
