<?php

namespace App\Livewire\Member;

use App\Enums\PointRecordType;
use App\Enums\RedemptionStatus;
use App\Models\Redemption;
use App\Models\Reward;
use App\Traits\Components\WithConfirmation;
use App\Traits\Components\WithToast;
use Flux\Flux;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Title('Hadiah')]
#[Layout('components.layouts.member')]
class RedeemPoint extends Component
{
    use WithConfirmation, WithToast;

    public array $rewards = [];

    public array $userRedemptions = [];

    public function mount(): void
    {
        $userTierId = auth()->user()->membership->tier_id;

        $this->rewards = Reward::show()
            ->active()
            ->whereHas('tiers', function ($query) use ($userTierId) {
                $query->where('id', $userTierId);
            })
            ->orderBy('points')
            ->get()
            ->map(function (Reward $reward) {
                $reward->thumbnail = $reward->getFirstMediaUrl('thumbnail');
                $reward->category_label = $reward->category->label();

                return $reward;
            })
            ->toArray();

        $this->userRedemptions = Redemption::with('reward')
            ->where('user_id', auth()->id())
            ->latest()
            ->get()
            ->map(function (Redemption $redemption) {
                $redemption->status_label = $redemption->status->label();
                $redemption->status_color = $redemption->status->color();

                return $redemption;
            })
            ->toArray();
    }

    public function redeem(Reward $reward): void
    {
        $user = auth()->user();
        $membership = $user->membership;

        // Check if reward is available for user's tier
        if (! $reward->tiers()->where('tiers.id', $membership->tier_id)->exists()) {
            $this->toast('Hadiah ini tidak tersedia untuk tier Anda.', 'Gagal', 'danger');
            Flux::modals()->close();

            return;
        }

        if ($membership->reward_points < $reward->points) {
            $this->toast('Poin Anda tidak cukup untuk menukarkan hadiah ini.', 'Gagal', 'danger');

            Flux::modals()->close();

            return;
        }

        if ($reward->stock !== null && $reward->stock <= 0) {
            $this->toast('Stok hadiah ini sudah habis.', 'Gagal', 'danger');
            Flux::modals()->close();

            return;
        }

        $redemption = DB::transaction(function () use ($user, $membership, $reward) {
            // Deduct points from membership
            $membership->decrement('reward_points', $reward->points);

            // Create point record
            $user->pointRecords()->create([
                'change' => $reward->points,
                'type' => PointRecordType::REWARD,
                'is_addition' => false,
                'description' => Str::limit("Redeem: {$reward->name}", 50),
            ]);

            // Create redemption
            $redemption = Redemption::create([
                'user_id' => $user->id,
                'reward_id' => $reward->id,
                'code' => 'RD-'.Str::upper(Str::random(8)),
                'points_spent' => $reward->points,
                'status' => RedemptionStatus::WAITING_PICKUP,
                'expires_at' => now()->addWeek(),
            ]);

            // Decrement stock if applicable
            if ($reward->stock !== null) {
                $reward->decrement('stock');
            }

            return $redemption;
        });

        // Update rewards list in real-time
        $this->rewards = collect($this->rewards)->map(function ($item) use ($reward) {
            if ($item['id'] === $reward->getRouteKey() && $item['stock'] !== null) {
                $item['stock']--;
            }

            return $item;
        })->toArray();

        // Update user redemptions history in real-time
        $redemption->load('reward');
        array_unshift($this->userRedemptions, [
            ...$redemption->toArray(),
            'status_label' => $redemption->status->label(),
            'status_color' => $redemption->status->color(),
        ]);

        $this->toast('Hadiah berhasil ditukarkan! Silakan cek tab Riwayat untuk melihat kode penukaran Anda.');

        Flux::modals()->close();
    }

    public function render(): View
    {
        return view('livewire.member.rewards', [
            'pageTitle' => 'Penukaran Poin',
        ]);
    }
}
