<?php

namespace App\Livewire\Assignments;

use App\Domain\Scheduling\Enums\AssignmentScope;
use App\Domain\Scheduling\Enums\AssignmentStatus;
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\Models\User;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('إنشاء تكليف')]
class AssignmentForm extends Component
{
    use UsesBranchScope;

    public string $user_id = '';
    public string $assignable_type = 'group';
    public string $assignable_id = '';
    public string $scope = 'full';
    public string $role_label = '';
    public string $start_date = '';
    public ?string $end_date = null;
    public ?string $start_time = null;
    public ?string $end_time = null;
    public bool $is_primary = false;
    public string $notes = '';
    public array $schedule_days = [];

    public function mount(): void
    {
        $this->authorize('assignments.create');
        $this->start_date = now()->format('Y-m-d');
    }

    public function updatedAssignableType(): void
    {
        $this->assignable_id = '';
    }

    public function rules(): array
    {
        return [
            'user_id' => 'required|exists:users,id',
            'assignable_type' => 'required|in:group,session',
            'assignable_id' => 'required|integer|min:1',
            'scope' => 'required|in:full,partial,supervising,assisting,observing',
            'role_label' => 'nullable|string|max:100',
            'start_date' => 'required|date',
            'end_date' => 'nullable|date|after_or_equal:start_date',
            'start_time' => 'nullable|date_format:H:i',
            'end_time' => 'nullable|date_format:H:i|after:start_time',
            'is_primary' => 'boolean',
            'notes' => 'nullable|string|max:1000',
            'schedule_days' => 'nullable|array',
            'schedule_days.*' => 'integer|between:0,6',
        ];
    }

    public function messages(): array
    {
        return [
            'user_id.required' => 'يجب اختيار المستخدم',
            'user_id.exists' => 'المستخدم غير موجود',
            'assignable_type.required' => 'يجب اختيار نوع التكليف',
            'assignable_type.in' => 'نوع التكليف غير صالح',
            'assignable_id.required' => 'يجب اختيار المجموعة أو الحصة',
            'assignable_id.integer' => 'اختيار غير صالح',
            'scope.required' => 'نطاق التكليف مطلوب',
            'scope.in' => 'نطاق التكليف غير صالح',
            'role_label.max' => 'المسمى الوظيفي يجب ألا يتجاوز 100 حرف',
            'start_date.required' => 'تاريخ البداية مطلوب',
            'start_date.date' => 'تاريخ البداية غير صالح',
            'end_date.date' => 'تاريخ النهاية غير صالح',
            'end_date.after_or_equal' => 'تاريخ النهاية يجب أن يكون بعد أو يساوي تاريخ البداية',
            'start_time.date_format' => 'وقت البداية يجب أن يكون بصيغة ساعة:دقيقة',
            'end_time.date_format' => 'وقت النهاية يجب أن يكون بصيغة ساعة:دقيقة',
            'end_time.after' => 'وقت النهاية يجب أن يكون بعد وقت البداية',
            'notes.max' => 'الملاحظات يجب ألا تتجاوز 1000 حرف',
            'schedule_days.array' => 'أيام الجدول غير صالحة',
            'schedule_days.*.between' => 'يوم غير صالح',
        ];
    }

    public function save(AssignmentService $service): void
    {
        $this->validate();

        try {
            $user = User::findOrFail($this->user_id);

            if ($this->assignable_type === 'group') {
                $assignable = TrainingGroup::findOrFail($this->assignable_id);
            } else {
                $assignable = TrainingSession::findOrFail($this->assignable_id);
            }

            $service->assign($user, $assignable, [
                'scope' => $this->scope,
                'role_label' => $this->role_label ?: null,
                'start_date' => $this->start_date,
                'end_date' => $this->end_date ?: null,
                'start_time' => $this->start_time ?: null,
                'end_time' => $this->end_time ?: null,
                'is_primary' => $this->is_primary,
                'notes' => $this->notes ?: null,
                'schedule_days' => $this->schedule_days,
            ], auth()->user());

            session()->flash('success', __('تم إنشاء التكليف بنجاح'));
            $this->redirect(route('assignments.list'), navigate: true);
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function render()
    {
        $assignableOptions = [];

        if ($this->assignable_type === 'group') {
            $assignableOptions = TrainingGroup::query()
                ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
                ->orderBy('name_ar')
                ->get(['id', 'name_ar', 'name'])
                ->mapWithKeys(fn ($g) => [$g->id => $g->name_ar])
                ->toArray();
        } elseif ($this->assignable_type === 'session') {
            $assignableOptions = TrainingSession::with('group')
                ->when($branchId, fn ($q) => $q->whereHas('group', fn ($g) => $g->where('branch_id', $branchId)))
                ->orderByDesc('session_date')
                ->limit(100)
                ->get()
                ->mapWithKeys(fn ($s) => [
                    $s->id => ($s->group?->name_ar ?? '') . ' - ' . ($s->session_date?->format('Y-m-d') ?? ''),
                ])
                ->toArray();
        }

        return view('livewire.assignments.assignment-form', [
            'users' => User::where('status', 'active')->orderBy('name_ar')->get(['id', 'name_ar', 'name']),
            'scopeOptions' => collect(AssignmentScope::cases())->mapWithKeys(fn ($s) => [$s->value => $s->label()]),
            'assignableOptions' => $assignableOptions,
            'dayLabels' => [
                0 => __('الأحد'),
                1 => __('الإثنين'),
                2 => __('الثلاثاء'),
                3 => __('الأربعاء'),
                4 => __('الخميس'),
                5 => __('الجمعة'),
                6 => __('السبت'),
            ],
        ]);
    }
}
