<?php

namespace App\Livewire\Enrollments;

use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use App\Domain\Training\Services\EnrollmentService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

#[Layout('layouts.app')]
#[Title('التسجيلات')]
class EnrollmentList extends Component
{
    use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;

    protected string $scopePermission = 'enrollments.list';

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

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

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

    public string $groupFilter = '';
    public string $paymentFilter = '';

    public function mount(): void
    {
        if (!request()->has('sortBy')) {
            $this->sortBy = 'enrollment_date';
        }
    }

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

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

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

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

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

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

        try {
            // $enrollmentId comes straight from the browser. The lookup is safe
            // because Enrollment carries BranchScope: an id from another branch
            // resolves to nothing and 404s here rather than cascading a cancel
            // into that branch's invoices.
            $enrollment = Enrollment::findOrFail($enrollmentId);
            $service = app(EnrollmentService::class);
            $service->cancel($enrollment, $reason, auth()->user());
            session()->flash('success', __('تم إلغاء التسجيل بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function render()
    {
        // No branch clause anywhere below: Enrollment, TrainingGroup and
        // TrainingProgram all carry a branch global scope now. The old
        // whereHas('group', branch_id) filter was not just redundant, it also
        // dropped every enrolment whose group had been soft-deleted.
        $query = Enrollment::query()
            ->with(['participant.person', 'group', 'program'])
            ->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->status, fn ($q) => $q->where('status', $this->status))
            ->when($this->programFilter, fn ($q) => $q->where('training_program_id', $this->programFilter))
            ->when($this->groupFilter, fn ($q) => $q->where('training_group_id', $this->groupFilter))
            ->when($this->paymentFilter, fn ($q) => $q->where('payment_status', $this->paymentFilter));

        // These joins are for ORDER BY only — the select stays enrollments.*, and
        // the driving table is already narrowed by BranchScope, so a join row
        // cannot introduce another branch's record. Nothing to filter here.
        if ($this->sortBy === 'name_ar') {
            $query->join('participants', 'enrollments.participant_id', '=', 'participants.id')
                  ->join('people', 'participants.person_id', '=', 'people.id')
                  ->orderBy('people.name_ar', $this->sortDir)
                  ->select('enrollments.*');
        } elseif ($this->sortBy === 'group_name') {
            $query->join('training_groups', 'enrollments.training_group_id', '=', 'training_groups.id')
                  ->orderBy('training_groups.name_ar', $this->sortDir)
                  ->select('enrollments.*');
        } else {
            $query->orderBy($this->sortBy, $this->sortDir);
        }

        $this->applyRoleScope($query);

        $groups = TrainingGroup::whereIn('status', ['forming', 'active', 'full'])
            ->when($this->programFilter, fn ($q) => $q->where('training_program_id', $this->programFilter))
            ->orderBy('name_ar')
            ->get(['id', 'name_ar']);

        return view('livewire.enrollments.enrollment-list', [
            'enrollments' => $query->paginate(20),
            'programs' => TrainingProgram::where('status', 'active')->orderBy('name_ar')->get(['id', 'name_ar']),
            'groups' => $groups,
            'statusOptions' => [
                'pending' => 'معلق',
                'active' => 'نشط',
                'completed' => 'مكتمل',
                'cancelled' => 'ملغي',
                'expired' => 'منتهي',
                'waitlisted' => 'قائمة انتظار',
            ],
            'paymentOptions' => [
                'paid' => 'مدفوع',
                'pending' => 'معلق',
                'partial' => 'جزئي',
                'overdue' => 'متأخر',
                'waived' => 'معفى',
            ],
        ]);
    }
}
