<?php

namespace App\Livewire\Admin\Voucher;

use App\Models\Voucher;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
use Livewire\WithPagination;

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

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

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

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

    // ── Form fields ──────────────────────────────────────────────────────
    public string  $code         = '';
    public string  $type         = 'percent';
    public string  $value        = '';
    public string  $min_order    = '0';
    public string  $max_discount = '';
    public string  $quota        = '';
    public string  $valid_from   = '';
    public string  $valid_until  = '';
    public bool    $is_active    = true;

    protected function rules(): array
    {
        return [
            'code'         => ['required', 'string', 'max:50', 'alpha_num',
                               Rule::unique('vouchers', 'code')
                                   ->ignore($this->editingId)
                                   ->whereNull('deleted_at')],
            'type'         => ['required', 'in:percent,fixed'],
            'value'        => ['required', 'numeric', 'min:0.01'],
            'min_order'    => ['nullable', 'numeric', 'min:0'],
            'max_discount' => ['nullable', 'numeric', 'min:0'],
            'quota'        => ['nullable', 'integer', 'min:1'],
            'valid_from'   => ['nullable', 'date'],
            'valid_until'  => ['nullable', 'date', 'after_or_equal:valid_from'],
            'is_active'    => ['boolean'],
        ];
    }

    protected $messages = [
        'code.required'              => 'Kode voucher wajib diisi.',
        'code.alpha_num'             => 'Kode hanya boleh huruf dan angka.',
        'code.unique'                => 'Kode voucher sudah digunakan.',
        'value.required'             => 'Nilai diskon wajib diisi.',
        'value.min'                  => 'Nilai diskon harus lebih dari nol.',
        'quota.min'                  => 'Kuota minimal 1.',
        'valid_until.after_or_equal' => 'Tanggal akhir harus sama atau setelah tanggal mulai.',
    ];

    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';
        }
    }

    public function generateCode(): void
    {
        $this->code = strtoupper(Str::random(8));
    }

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

        $this->resetForm();
        $this->valid_from  = now()->format('Y-m-d');
        $this->valid_until = now()->addDays(30)->format('Y-m-d');
        $this->showModal   = true;
    }

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

        $v = Voucher::findOrFail($id);
        $this->editingId    = $v->id;
        $this->code         = $v->code;
        $this->type         = $v->type;
        $this->value        = (string) $v->value;
        $this->min_order    = (string) $v->min_order;
        $this->max_discount = $v->max_discount ? (string) $v->max_discount : '';
        $this->quota        = $v->quota ? (string) $v->quota : '';
        $this->valid_from   = $v->valid_from?->format('Y-m-d') ?? '';
        $this->valid_until  = $v->valid_until?->format('Y-m-d') ?? '';
        $this->is_active    = $v->is_active;
        $this->showModal    = true;
    }

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

        $data = $this->validate();

        $mapped = [
            'code'         => strtoupper($data['code']),
            'type'         => $data['type'],
            'value'        => $data['value'],
            'min_order'    => $data['min_order'] ?: 0,
            'max_discount' => ($data['type'] === 'percent' && $data['max_discount'] !== '')
                                ? $data['max_discount'] : null,
            'quota'        => $data['quota'] ?: null,
            'valid_from'   => $data['valid_from'] ?: null,
            'valid_until'  => $data['valid_until'] ?: null,
            'is_active'    => $data['is_active'],
        ];

        if ($this->editingId) {
            Voucher::findOrFail($this->editingId)->update($mapped);
            $this->dispatch('notify', type: 'success', message: 'Voucher berhasil diperbarui.');
        } else {
            Voucher::create(array_merge($mapped, ['used_count' => 0]));
            $this->dispatch('notify', type: 'success', message: 'Voucher berhasil ditambahkan.');
        }

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

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

        $this->deleteId   = $id;
        $this->showDelete = true;
    }

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

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

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

    private function resetForm(): void
    {
        $this->editingId    = null;
        $this->code         = '';
        $this->type         = 'percent';
        $this->value        = '';
        $this->min_order    = '0';
        $this->max_discount = '';
        $this->quota        = '';
        $this->valid_from   = '';
        $this->valid_until  = '';
        $this->is_active    = true;
        $this->resetValidation();
    }

    public function render()
    {
        $today = now()->toDateString();

        $vouchers = Voucher::query()
            ->when($this->search, fn ($q) =>
                $q->where('code', 'like', "%{$this->search}%"))
            ->when($this->filterStatus === 'active', fn ($q) =>
                $q->where('is_active', true)
                  ->where(fn ($q) => $q->whereNull('valid_until')->orWhereDate('valid_until', '>=', $today)))
            ->when($this->filterStatus === 'inactive', fn ($q) =>
                $q->where('is_active', false))
            ->when($this->filterStatus === 'expired', fn ($q) =>
                $q->whereNotNull('valid_until')->whereDate('valid_until', '<', $today))
            ->orderBy($this->sortBy, $this->sortDirection)
            ->paginate(15);

        // Statistik dihitung terpisah dari hasil filter/paginasi
        // agar selalu menampilkan total keseluruhan, bukan hasil filter.
        $stats = [
            'total'   => Voucher::count(),
            'active'  => Voucher::where('is_active', true)
                ->where(fn ($q) => $q->whereNull('valid_until')->orWhereDate('valid_until', '>=', $today))
                ->count(),
            'expired' => Voucher::whereNotNull('valid_until')->whereDate('valid_until', '<', $today)->count(),
            'used'    => (int) Voucher::sum('used_count'),
        ];

        return view('livewire.admin.voucher.index', compact('vouchers', 'stats'));
    }
}
