<?php

namespace App\Livewire\Groups;

use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Enums\GroupStatus;
use App\Domain\Training\Models\Activity;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use App\Domain\Training\Services\TrainingGroupService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use Illuminate\Support\Facades\DB;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

#[Layout('layouts.app')]
#[Title('المجموعات التدريبية')]
class GroupList extends Component
{
    use WithPagination, WithSorting, UsesBranchScope, AppliesRoleScope;

    protected string $scopePermission = 'groups.list';

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

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

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

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


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

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

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

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

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

    public function changeStatus(string $uuid, string $newStatus, TrainingGroupService $service): void
    {
        // The route carries groups.list only; deleteGroup() already re-checks
        // its own permission here and this write needs the same gate, since a
        // Livewire action is callable whether or not its button was rendered.
        $this->authorize('groups.update');

        try {
            $group = TrainingGroup::where('uuid', $uuid)->firstOrFail();
            $service->changeStatus($group, $newStatus, auth()->user());
            session()->flash('success', __('تم تحديث حالة المجموعة بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function deleteGroup(string $uuid): void
    {
        $this->authorize('groups.delete');

        $group = TrainingGroup::where('uuid', $uuid)->firstOrFail();

        try {
            DB::transaction(function () use ($group) {
                // Nullify transferred_to_id references from other enrollments.
                // Deliberately across branches: a transfer may have moved a
                // player to a group in another branch, and enrollments.
                // transferred_to_id has no ON DELETE clause — a reference left
                // behind because the scope hid it would abort the delete with a
                // foreign-key violation.
                \App\Domain\Training\Models\Enrollment::withoutBranchScope()
                    ->where('transferred_to_id', $group->id)
                    ->update(['transferred_to_id' => null]);
                // Sessions cascade-delete their attendance records automatically
                $group->sessions()->forceDelete();
                $group->schedules()->delete();
                $group->enrollments()->forceDelete();
                $group->waitlists()->delete();
                $group->forceDelete();
            });

            session()->flash('success', __('تم حذف المجموعة وجميع البيانات المرتبطة بها'));
        } catch (\Throwable $e) {
            session()->flash('error', __('فشل حذف المجموعة: ') . $e->getMessage());
        }
    }

    public function render()
    {
        // No branch clause. TrainingGroup is strict-scoped, so BranchScope has
        // already narrowed this to the active branch; restating it here read as
        // if the filtering lived on this screen, which is exactly the habit
        // that left the <select>s beside it unfiltered.
        $query = TrainingGroup::query()
            ->with(['program', 'branch', 'headTrainer'])
            ->when($this->search, fn ($q) => $q->where(function ($sub) {
                $sub->where('name_ar', 'ilike', "%{$this->search}%")
                    ->orWhere('name', 'ilike', "%{$this->search}%")
                    ->orWhere('code', 'ilike', "%{$this->search}%");
            }))
            ->when($this->status, fn ($q) => $q->where('status', $this->status))
            ->when($this->activityFilter, fn ($q) => $q->whereHas('program', fn ($p) => $p->where('activity_id', $this->activityFilter)))
            ->when($this->programFilter, fn ($q) => $q->where('training_program_id', $this->programFilter))
            ->orderBy($this->sortBy, $this->sortDir);

        $this->applyRoleScope($query);

        $programs = TrainingProgram::query()
            ->when($this->activityFilter, fn ($q) => $q->where('activity_id', $this->activityFilter))
            ->orderBy('name_ar')
            ->get(['id', 'name_ar']);

        return view('livewire.groups.group-list', [
            'groups' => $query->paginate(15),
            'activities' => Activity::where('is_active', true)->orderBy('name_ar')->get(['id', 'name_ar']),
            'programs' => $programs,
            'statusOptions' => [
                'forming' => 'قيد التشكيل',
                'active' => 'نشطة',
                'full' => 'ممتلئة',
                'on_hold' => 'متوقفة',
                'completed' => 'مكتملة',
                'cancelled' => 'ملغاة',
            ],
        ]);
    }
}
