<?php

namespace App\Livewire\Admin\Ongkir;

use App\Models\DeliveryArea;
use App\Models\Order;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
use Livewire\WithPagination;

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

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

    // ── Sorting ───────────────────────────────────────────────────────────
    public string $sortBy        = 'name'; // name | cost | orders_count
    public string $sortDirection = 'asc';

    // ── Modal state ──────────────────────────────────────────────────────
    public bool $showModal  = false;
    public bool $showDelete = false;
    public ?int $editingId  = null;
    public ?int $deleteId   = null;

    // ── Form fields ──────────────────────────────────────────────────────
    public string $name                 = '';
    public string $cost                 = '';
    public string $estimasi_pengiriman  = '';
    public string $keterangan           = '';
    public int    $is_active            = 1;

    protected function rules(): array
    {
        return [
            'name' => [
                'required', 'string', 'max:150',
                Rule::unique('delivery_areas', 'name')->ignore($this->editingId),
            ],
            'cost'                => ['required', 'numeric', 'min:0.01'],
            'estimasi_pengiriman' => ['nullable', 'string', 'max:100'],
            'keterangan'          => ['nullable', 'string', 'max:1000'],
            'is_active'           => ['required', 'in:0,1'],
        ];
    }

    protected $messages = [
        'name.required' => 'Nama area wajib diisi.',
        'name.unique'   => 'Nama area sudah digunakan, gunakan nama lain.',
        'cost.required' => 'Biaya ongkir wajib diisi.',
        'cost.numeric'  => 'Biaya ongkir harus berupa angka.',
        'cost.min'      => 'Biaya ongkir harus lebih dari nol.',
    ];

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

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

    // ── CRUD Actions ─────────────────────────────────────────────────────

    public function create(): void
    {
        abort_unless(auth()->user()->can('delivery.create'), 403);

        $this->resetForm();
        $this->showModal = true;
    }

    public function edit(int $id): void
    {
        abort_unless(auth()->user()->can('delivery.edit'), 403);

        $area = DeliveryArea::findOrFail($id);
        $this->editingId           = $area->id;
        $this->name                = $area->name;
        $this->cost                = (string) $area->cost;
        $this->estimasi_pengiriman = $area->estimasi_pengiriman ?? '';
        $this->keterangan          = $area->keterangan ?? '';
        $this->is_active           = (int) $area->is_active;
        $this->showModal           = true;
    }

    public function save(): void
    {
        $permission = $this->editingId ? 'delivery.edit' : 'delivery.create';
        abort_unless(auth()->user()->can($permission), 403);

        $data = $this->validate();

        if ($this->editingId) {
            DeliveryArea::findOrFail($this->editingId)->update($data);
            $this->dispatch('notify', type: 'success', message: 'Area ongkir berhasil diperbarui.');
        } else {
            DeliveryArea::create($data);
            $this->dispatch('notify', type: 'success', message: 'Area ongkir berhasil ditambahkan.');
        }

        $this->showModal = false;
        $this->resetForm();
    }

    public function confirmDelete(int $id): void
    {
        abort_unless(auth()->user()->can('delivery.delete'), 403);

        $count = DeliveryArea::withCount('orders')->findOrFail($id)->orders_count;
        if ($count > 0) {
            $this->dispatch('notify', type: 'error',
                message: "Tidak bisa dihapus. Area ini sudah dipakai pada {$count} pesanan.");
            return;
        }
        $this->deleteId   = $id;
        $this->showDelete = true;
    }

    public function delete(): void
    {
        abort_unless(auth()->user()->can('delivery.delete'), 403);

        DeliveryArea::findOrFail($this->deleteId)->delete();
        $this->showDelete = false;
        $this->deleteId   = null;
        $this->dispatch('notify', type: 'success', message: 'Area ongkir berhasil dihapus.');
    }

    public function toggleActive(int $id): void
    {
        $area = DeliveryArea::findOrFail($id);
        $area->update(['is_active' => ! $area->is_active]);
        $label = $area->fresh()->is_active ? 'diaktifkan' : 'dinonaktifkan';
        $this->dispatch('notify', type: 'success', message: "Area ongkir berhasil {$label}.");
    }

    private function resetForm(): void
    {
        $this->editingId           = null;
        $this->name                = '';
        $this->cost                = '';
        $this->estimasi_pengiriman = '';
        $this->keterangan          = '';
        $this->is_active           = 1;
        $this->resetValidation();
    }

    public function render()
    {
        $areas = DeliveryArea::withCount('orders')
            ->when($this->search, fn ($q) =>
                $q->where('name', 'like', "%{$this->search}%"))
            ->when($this->filterStatus !== '', fn ($q) =>
                $q->where('is_active', $this->filterStatus === 'active'))
            ->when($this->sortBy === 'orders_count',
                fn ($q) => $q->orderBy('orders_count', $this->sortDirection),
                fn ($q) => $q->orderBy($this->sortBy, $this->sortDirection)
            )
            ->paginate(15);

        // Statistik dihitung terpisah dari hasil filter/paginasi
        // agar selalu menampilkan total keseluruhan, bukan hasil filter.
        // Total order dihitung langsung dari tabel orders (1 query agregat),
        // bukan dengan memuat seluruh record DeliveryArea ke memory.
        $stats = [
            'total'    => DeliveryArea::count(),
            'active'   => DeliveryArea::where('is_active', true)->count(),
            'inactive' => DeliveryArea::where('is_active', false)->count(),
            'orders'   => Order::whereNotNull('delivery_area_id')->count(),
        ];

        return view('livewire.admin.ongkir.index', compact('areas', 'stats'));
    }
}
