<?php

namespace App\Livewire\Home;

use App\Models\Outlet;
use App\Models\Voucher as VoucherModel;
use App\Traits\Components\WithToast;
use Carbon\Carbon;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Component;
use Livewire\WithoutUrlPagination;
use Livewire\WithPagination;

#[Layout('components.layouts.home', [
    'title' => 'Voucher',
])]
class Voucher extends Component
{
    use WithoutUrlPagination, WithPagination, WithToast;

    public array $outlets = [];

    public ?string $search = null;

    public ?string $outlet_id = null;

    public ?string $sort = null;

    public ?VoucherModel $selectedVoucher = null;

    public bool $showDetailModal = false;

    public function mount(): void
    {
        $this->outlets = Outlet::query()->operational()->pluck('name', 'id')->toArray();
    }

    public function updatedSearch(): void
    {
        $this->resetPage();
    }

    public function updatedOutletId(): void
    {
        $this->resetPage();
    }

    public function updatedSort(): void
    {
        $this->resetPage();
    }

    public function showDetail(VoucherModel $voucher): void
    {
        $this->selectedVoucher = $voucher;
        $this->selectedVoucher->load(['outlets', 'tiers']);

        $this->showDetailModal = true;
    }

    public function closeDetail(): void
    {
        $this->showDetailModal = false;
        $this->selectedVoucher = null;
    }

    public function claim(VoucherModel $voucher): void
    {
        $user = auth()->user();

        if (! auth()->check()) {
            $this->redirect(route('login'), navigate: true);

            return;
        }

        // 1. Check if voucher exists and is active
        if (
            Carbon::parse($voucher->start_date)->gt(now()) ||
            (
                $voucher->end_date &&
                Carbon::parse($voucher->end_date)->lt(now())
            )
        ) {
            $this->toast('Voucher tidak tersedia atau sudah kadaluarsa.', 'Gagal', 'danger');

            return;
        }

        // 2. Check Tier Requirement (before transaction)
        $userTierId = $user->membership?->tier_id;

        $voucher->load('tiers'); // Ensure tiers are loaded
        $voucherTierIds = $voucher->tiers->pluck('id');

        if (
            $voucherTierIds->isNotEmpty() &&
            (! $userTierId || ! $voucherTierIds->contains($userTierId))
        ) {
            $this->toast('Voucher ini hanya tersedia untuk tier tertentu.', 'Gagal', 'danger');

            return;
        }

        // 3. Execute claim within transaction for data consistency
        $result = DB::transaction(function () use ($user, $voucher) {
            // Lock voucher row to prevent race condition
            $v = VoucherModel::whereKey($voucher->id)
                ->lockForUpdate()
                ->first();

            if (! $v) {
                return 'not_found';
            }

            // Check if available_count (stock) is sufficient
            // available_count harus > 0 untuk bisa di-claim
            if ($v->quota !== null && $v->available_count <= 0) {
                return 'stock_empty';
            }

            // Check how many times this user has claimed this voucher
            // Using SUM quantity to calculate total voucher that has been claimed
            $userClaimedQuantity = DB::table('user_voucher')
                ->where('user_id', $user->id)
                ->where('voucher_id', $v->id)
                ->sum('quantity');

            // Check if user has reached the limit
            if ($v->limit_per_user !== null && $userClaimedQuantity >= $v->limit_per_user) {
                return 'limit_reached';
            }

            // Check if user already has a record for this voucher
            $existingPivot = DB::table('user_voucher')
                ->where('user_id', $user->id)
                ->where('voucher_id', $v->id)
                ->first();

            if ($existingPivot) {
                // User already has this voucher, increment the quantity
                DB::table('user_voucher')
                    ->where('user_id', $user->id)
                    ->where('voucher_id', $v->id)
                    ->update([
                        'quantity' => $existingPivot->quantity + 1,
                        'updated_at' => now(),
                    ]);
            } else {
                // User doesn't have this voucher yet, create new record
                $user->vouchers()->attach($v->id, [
                    'quantity' => 1,
                    'created_at' => now(),
                    'updated_at' => now(),
                ]);
            }

            // Decrease available stock
            $v->decrement('available_count');

            return 'success';
        });

        // Handle transaction results
        if ($result === 'not_found') {
            $this->toast('Voucher tidak ditemukan.', 'Gagal', 'danger');

            return;
        }

        if ($result === 'stock_empty') {
            $this->toast('Klaim gagal! Kuota voucher sudah habis.', 'Gagal', 'danger');

            return;
        }

        if ($result === 'limit_reached') {
            $this->toast('Anda sudah mencapai batas maksimal klaim voucher ini.', 'Peringatan', 'warning');

            return;
        }

        if ($result === 'success') {
            $this->toast(
                'Voucher berhasil diklaim! Silakan cek di menu Voucher di halaman dasbor.',
                'Berhasil',
                'success'
            );
        }
    }

    public function render(): View
    {
        $vouchers = VoucherModel::query()
            ->with(['tiers', 'outlets'])
            ->active()
            ->show()
            ->where(function ($query) {
                $query->where('name', 'like', '%'.$this->search.'%')
                    ->orWhere('code', 'like', '%'.$this->search.'%');
            })
            ->when($this->outlet_id, function ($query) {
                $query->whereHas('outlets', function ($q) {
                    $q->where('outlets.id', $this->outlet_id);
                });
            })
            ->when($this->sort, function ($query) {
                match ($this->sort) {
                    'latest' => $query->orderBy('created_at', 'desc'),
                    'biggest' => $query->orderBy('discount_amount', 'desc'),
                    'ending-soon' => $query->orderByRaw('end_date IS NULL')->orderBy('end_date', 'asc'),
                    default => $query->latest(),
                };
            }, fn ($query) => $query->latest())
            ->paginate(6);

        $user = auth()->user();
        $userTierId = $user?->membership?->tier_id;

        $voucherIds = $vouchers->pluck('id');
        if ($this->selectedVoucher) {
            $voucherIds->push($this->selectedVoucher->id);
        }

        $userClaimedCounts = $user
            ? DB::table('user_voucher')
                ->where('user_id', $user->id)
                ->whereIn('voucher_id', $voucherIds->unique())
                ->select('voucher_id', DB::raw('SUM(quantity) as total_quantity'))
                ->groupBy('voucher_id')
                ->pluck('total_quantity', 'voucher_id')
                ->toArray()
            : [];

        return view('livewire.home.vouchers', [
            'pageTitle' => 'Voucher',
            'pageDesc' => 'Nikmati berbagai voucher menarik untuk belanja lebih hemat dan menyenangkan.',
            'vouchers' => $vouchers,
        ]);
    }
}
