<?php

namespace App\Livewire\Enrollments;

use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Enums\EnrollmentStatus;
use App\Domain\Training\Events\WaitlistSpotAvailable;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

#[Layout('layouts.app')]
#[Title('قائمة الانتظار')]
class WaitlistManager extends Component
{
    use WithPagination, UsesBranchScope;

    #[Url]
    public string $search = '';

    #[Url]
    public string $groupFilter = '';

    #[Url]
    public string $programFilter = '';

    public function mount(): void
    {
        $this->authorize('enrollments.list');
    }

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

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

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

    public function promote(int $enrollmentId): void
    {
        $this->authorize('enrollments.update');

        $enrollment = Enrollment::where('status', EnrollmentStatus::Waitlisted)->findOrFail($enrollmentId);

        $group = $enrollment->group;

        if ($group && $group->isFull()) {
            session()->flash('error', __('المجموعة ممتلئة، لا يمكن الترقية'));
            return;
        }

        $enrollment->update(['status' => 'pending']);

        // Update group counts
        if ($group) {
            $group->decrement('waitlist_count');
        }

        // Dispatch event for notification
        WaitlistSpotAvailable::dispatch($group, $enrollment);

        session()->flash('success', __('تم ترقية المشترك من قائمة الانتظار بنجاح'));
    }

    public function cancel(int $enrollmentId, string $reason): void
    {
        $this->authorize('enrollments.cancel');

        $enrollment = Enrollment::where('status', EnrollmentStatus::Waitlisted)->findOrFail($enrollmentId);

        $enrollment->update([
            'status' => 'cancelled',
            'withdrawal_reason' => $reason,
            'withdrawal_date' => now(),
        ]);

        // Update group waitlist count
        if ($enrollment->group) {
            $enrollment->group->decrement('waitlist_count');
        }

        session()->flash('success', __('تم إلغاء التسجيل من قائمة الانتظار'));
    }

    public function render()
    {
        $branchId = $this->getActiveBranchId();

        $query = Enrollment::query()
            ->where('status', EnrollmentStatus::Waitlisted)
            ->with(['participant.person', 'group', 'program'])
            ->when($branchId, fn ($q) => $q->whereHas('group', fn ($gq) => $gq->where('branch_id', $branchId)))
            ->when($this->search, function ($q) {
                $search = $this->search;
                $q->where(function ($q2) use ($search) {
                    $q2->whereHas('participant.person', function ($pq) use ($search) {
                        $pq->where('name_ar', 'ilike', "%{$search}%")
                           ->orWhere('name', 'ilike', "%{$search}%");
                    })->orWhereHas('participant', function ($pq) use ($search) {
                        $pq->where('participant_number', 'ilike', "%{$search}%");
                    });
                });
            })
            ->when($this->groupFilter, fn ($q) => $q->where('training_group_id', $this->groupFilter))
            ->when($this->programFilter, fn ($q) => $q->where('training_program_id', $this->programFilter))
            ->orderBy('enrollment_date');

        return view('livewire.enrollments.waitlist-manager', [
            'enrollments' => $query->paginate(20),
            'groups' => TrainingGroup::whereIn('status', ['forming', 'active', 'full'])
                ->orderBy('name_ar')
                ->get(['id', 'name_ar', 'current_count', 'max_capacity']),
            'programs' => TrainingProgram::where('status', 'active')
                ->orderBy('name_ar')
                ->get(['id', 'name_ar']),
        ]);
    }
}
