<?php

namespace App\Livewire\Admin\Banner;

use App\Models\Banner;
use Illuminate\Support\Facades\Storage;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\WithPagination;

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

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

    // ── Sorting ───────────────────────────────────────────────────────────
    public string $sortBy        = 'sort_order'; // title | sort_order | created_at
    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  $title      = '';
    public string  $link_url   = '';
    public bool    $is_active  = true;
    public int     $sort_order = 0;
    public $image  = null;
    public ?string $existing_image = null;

    protected function rules(): array
    {
        $isEdit = (bool) $this->editingId;
        return [
            'title'      => ['required', 'string', 'max:200'],
            'image'      => [$isEdit ? 'nullable' : 'required', 'image',
                             'mimes:jpg,jpeg,png,webp', 'max:3072'],
            'link_url'   => ['nullable', 'url', 'max:500'],
            'is_active'  => ['boolean'],
            'sort_order' => ['integer', 'min:0'],
        ];
    }

    protected $messages = [
        'title.required'  => 'Judul banner wajib diisi.',
        'image.required'  => 'Gambar banner wajib diunggah.',
        'image.image'     => 'File harus berupa gambar.',
        'image.mimes'     => 'Format gambar harus JPG, PNG, atau WEBP.',
        'image.max'       => 'Ukuran gambar maksimal 3MB.',
        'link_url.url'    => 'Format URL tidak valid (harus diawali https://).',
    ];

    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 create(): void
    {
        abort_unless(auth()->user()->can('banner.create'), 403);

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

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

        $banner = Banner::findOrFail($id);
        $this->editingId      = $banner->id;
        $this->title          = $banner->title;
        $this->link_url       = $banner->link_url ?? '';
        $this->is_active      = $banner->is_active;
        $this->sort_order     = $banner->sort_order;
        $this->existing_image = $banner->image;
        $this->image          = null;
        $this->showModal      = true;
    }

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

        $this->validate();

        $data = [
            'title'      => $this->title,
            'link_url'   => $this->link_url ?: null,
            'is_active'  => $this->is_active,
            'sort_order' => $this->sort_order,
        ];

        if ($this->image) {
            if ($this->existing_image) {
                Storage::disk('public')->delete($this->existing_image);
            }
            $data['image'] = $this->image->store('banners', 'public');
        }

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

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

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

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

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

        $banner = Banner::findOrFail($this->deleteId);
        if ($banner->image) {
            Storage::disk('public')->delete($banner->image);
        }
        $banner->delete();
        $this->showDelete = false;
        $this->deleteId   = null;
        $this->dispatch('notify', type: 'success', message: 'Banner berhasil dihapus.');
    }

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

    private function resetForm(): void
    {
        $this->editingId      = null;
        $this->title          = '';
        $this->link_url       = '';
        $this->is_active      = true;
        $this->sort_order     = 0;
        $this->image          = null;
        $this->existing_image = null;
        $this->resetValidation();
    }

    public function render()
    {
        $banners = Banner::query()
            ->when($this->search, fn ($q) =>
                $q->where('title', 'like', "%{$this->search}%"))
            ->when($this->filterStatus !== '', fn ($q) =>
                $q->where('is_active', $this->filterStatus === 'active'))
            ->orderBy($this->sortBy, $this->sortDirection)
            ->paginate(12);

        return view('livewire.admin.banner.index', compact('banners'));
    }
}
