<?php

namespace App\Livewire\Assignments;

use App\Domain\Scheduling\Enums\AssignmentScope;
use App\Domain\Scheduling\Enums\AssignmentStatus;
use App\Domain\Scheduling\Models\Assignment;
use App\Domain\Scheduling\Services\AssignmentService;
use App\Domain\Shared\Exceptions\DomainException;
use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingSession;
use App\Livewire\Concerns\AppliesRoleScope;
use App\Livewire\Concerns\WithSorting;
use App\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

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

    protected string $scopePermission = 'assignments.list';

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

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

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

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

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

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

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

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

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

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

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

    public function suspend(string $uuid, AssignmentService $service): void
    {
        try {
            $assignment = Assignment::where('uuid', $uuid)->firstOrFail();
            $service->changeStatus($assignment, 'suspended', __('تم التعليق من قائمة التكليفات'));
            session()->flash('success', __('تم تعليق التكليف بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function activate(string $uuid, AssignmentService $service): void
    {
        try {
            $assignment = Assignment::where('uuid', $uuid)->firstOrFail();
            $service->changeStatus($assignment, 'active', __('تم إعادة التنشيط من قائمة التكليفات'));
            session()->flash('success', __('تم تنشيط التكليف بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function cancel(string $uuid, AssignmentService $service): void
    {
        try {
            $assignment = Assignment::where('uuid', $uuid)->firstOrFail();
            $service->changeStatus($assignment, 'cancelled', __('تم الإلغاء من قائمة التكليفات'));
            session()->flash('success', __('تم إلغاء التكليف بنجاح'));
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

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

        $query = Assignment::query()
            ->with(['user', 'assignable'])
            ->when($branchId, fn ($q) => $q->where(function ($sub) use ($branchId) {
                $sub->whereHasMorph('assignable', [TrainingGroup::class], fn ($gq) => $gq->where('branch_id', $branchId))
                    ->orWhereHasMorph('assignable', [TrainingSession::class], fn ($sq) => $sq->whereHas('group', fn ($gq) => $gq->where('branch_id', $branchId)));
            }))
            ->when($this->search, function ($q) {
                $search = $this->search;
                $q->whereHas('user', function ($q2) use ($search) {
                    $q2->where('name_ar', 'ilike', "%{$search}%")
                       ->orWhere('name', 'ilike', "%{$search}%");
                });
            })
            ->when($this->status, fn ($q) => $q->where('status', $this->status))
            ->when($this->scope, fn ($q) => $q->where('scope', $this->scope))
            ->when($this->assignableType, function ($q) {
                if ($this->assignableType === 'group') {
                    $q->where('assignable_type', TrainingGroup::class);
                } elseif ($this->assignableType === 'session') {
                    $q->where('assignable_type', TrainingSession::class);
                }
            })
            ->when($this->userId, fn ($q) => $q->where('user_id', $this->userId))
            ->orderBy($this->sortBy, $this->sortDir);

        $this->applyRoleScope($query);

        return view('livewire.assignments.assignment-list', [
            'assignments' => $query->paginate(20),
            'statusOptions' => collect(AssignmentStatus::cases())->mapWithKeys(fn ($s) => [$s->value => $s->label()]),
            'scopeOptions' => collect(AssignmentScope::cases())->mapWithKeys(fn ($s) => [$s->value => $s->label()]),
            'users' => User::where('status', 'active')->orderBy('name_ar')->get(['id', 'name_ar', 'name']),
        ]);
    }
}
