<?php

namespace App\Livewire\Admin\Customer;

use App\Models\GuestCustomer;
use App\Models\Order;
use App\Models\User;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
use Livewire\WithPagination;

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

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

    // ── Sorting ───────────────────────────────────────────────────────────
    public string $sortBy = 'newest'; // newest | oldest | name_asc | name_desc | spent_desc | spent_asc

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

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

    public function toggleActive(string $type, int $id): void
    {
        abort_unless(Auth::user()->can('customer.deactivate'), 403);

        // Guest customer tidak punya status aktif — abaikan jika dipanggil untuk guest
        if ($type !== 'user') {
            return;
        }

        $user = User::role('customer')->findOrFail($id);
        $user->update(['is_active' => ! $user->is_active]);

        $label = $user->fresh()->is_active ? 'diaktifkan' : 'dinonaktifkan';
        $this->dispatch('notify', type: 'success', message: "Akun customer berhasil {$label}.");
    }

    /**
     * Ambil seluruh Member (User berrole customer) dengan statistik order,
     * dipetakan menjadi struktur seragam agar bisa digabung dengan Guest.
     */
    private function getMembers(): Collection
    {
        return User::role('customer')
            ->withCount('orders')
            ->withSum('orders', 'grand_total')
            ->when($this->search, fn ($q) =>
                $q->where(function ($q) {
                    $q->where('name', 'like', "%{$this->search}%")
                      ->orWhere('email', 'like', "%{$this->search}%")
                      ->orWhere('phone', 'like', "%{$this->search}%");
                }))
            ->get()
            ->map(function (User $user) {
                return (object) [
                    'type'          => 'user',
                    'id'            => $user->id,
                    'name'          => $user->name,
                    'phone'         => $user->phone,
                    'email'         => $user->email,
                    'is_active'     => $user->is_active,
                    'orders_count'  => $user->orders_count,
                    'orders_sum'    => $user->orders_sum_grand_total ?? 0,
                    'joined_at'     => $user->created_at,
                ];
            });
    }

    /**
     * Ambil seluruh Guest Customer dengan statistik order,
     * dipetakan menjadi struktur seragam yang sama dengan Member.
     * Guest tidak punya email atau is_active — dikosongkan (null).
     */
    private function getGuests(): Collection
    {
        return GuestCustomer::query()
            ->withCount('orders')
            ->withSum('orders', 'grand_total')
            ->when($this->search, fn ($q) =>
                $q->where(function ($q) {
                    $q->where('name', 'like', "%{$this->search}%")
                      ->orWhere('phone', 'like', "%{$this->search}%");
                }))
            ->get()
            ->map(function (GuestCustomer $guest) {
                return (object) [
                    'type'          => 'guest',
                    'id'            => $guest->id,
                    'name'          => $guest->name,
                    'phone'         => $guest->phone,
                    'email'         => null,
                    'is_active'     => null,
                    'orders_count'  => $guest->orders_count,
                    'orders_sum'    => $guest->orders_sum_grand_total ?? 0,
                    'joined_at'     => $guest->created_at,
                ];
            });
    }

    public function render()
    {
        $members = $this->getMembers();
        $guests  = $this->getGuests();

        $all = $members->concat($guests);

        // ── Filter status ────────────────────────────────────────────────
        $all = match ($this->filterStatus) {
            'active'    => $all->where('is_active', true),
            'inactive'  => $all->where('is_active', false),
            'has_order' => $all->where('orders_count', '>', 0),
            'no_order'  => $all->where('orders_count', '=', 0),
            default     => $all,
        };

        // ── Sorting ──────────────────────────────────────────────────────
        $all = match ($this->sortBy) {
            'oldest'     => $all->sortBy('joined_at'),
            'name_asc'   => $all->sortBy(fn ($c) => strtolower($c->name)),
            'name_desc'  => $all->sortByDesc(fn ($c) => strtolower($c->name)),
            'spent_desc' => $all->sortByDesc('orders_sum'),
            'spent_asc'  => $all->sortBy('orders_sum'),
            default      => $all->sortByDesc('joined_at'), // newest
        };

        $all = $all->values();

        // ── Pagination manual ────────────────────────────────────────────
        $page    = $this->getPage();
        $offset  = ($page - 1) * $this->perPage;
        $items   = $all->slice($offset, $this->perPage)->values();

        $customers = new LengthAwarePaginator(
            $items,
            $all->count(),
            $this->perPage,
            $page,
            ['path' => request()->url(), 'pageName' => 'page']
        );

        return view('livewire.admin.customer.index', compact('customers'));
    }
}
