<?php

namespace App\Livewire\Schedule;

use App\Domain\Shared\Traits\UsesBranchScope;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use App\Domain\Training\Models\TrainingSession;
use App\Models\User;
use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Attributes\Url;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('الجدول الأسبوعي')]
class WeeklySchedule extends Component
{
    use UsesBranchScope;

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

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

    public string $weekStart = '';

    public function mount(): void
    {
        $this->authorize('schedules.view');

        // Start week on Saturday (Arabic week starts Saturday)
        $today = Carbon::today();
        $this->weekStart = $today->startOfWeek(Carbon::SATURDAY)->format('Y-m-d');
    }

    public function previousWeek(): void
    {
        $this->weekStart = Carbon::parse($this->weekStart)->subWeek()->format('Y-m-d');
    }

    public function nextWeek(): void
    {
        $this->weekStart = Carbon::parse($this->weekStart)->addWeek()->format('Y-m-d');
    }

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

    public function goToToday(): void
    {
        $today = Carbon::today();
        $this->weekStart = $today->startOfWeek(Carbon::SATURDAY)->format('Y-m-d');
    }

    #[Computed]
    public function weekDays(): array
    {
        $start = Carbon::parse($this->weekStart);
        $days = [];

        $arabicDayNames = [
            Carbon::SATURDAY => 'السبت',
            Carbon::SUNDAY => 'الأحد',
            Carbon::MONDAY => 'الاثنين',
            Carbon::TUESDAY => 'الثلاثاء',
            Carbon::WEDNESDAY => 'الأربعاء',
            Carbon::THURSDAY => 'الخميس',
        ];

        for ($i = 0; $i < 6; $i++) {
            $date = $start->copy()->addDays($i);
            $days[] = [
                'date' => $date->format('Y-m-d'),
                'name' => $arabicDayNames[$date->dayOfWeek] ?? $date->translatedDayName,
                'formatted' => $date->format('m/d'),
                'isToday' => $date->isToday(),
            ];
        }

        return $days;
    }

    #[Computed]
    public function timeSlots(): array
    {
        $slots = [];
        for ($hour = 8; $hour <= 22; $hour++) {
            $slots[] = sprintf('%02d:00', $hour);
        }

        return $slots;
    }

    public function render()
    {
        $branchId = $this->getActiveBranchId();
        $weekEnd = Carbon::parse($this->weekStart)->addDays(5)->format('Y-m-d');

        $sessions = TrainingSession::query()
            ->with(['group.program', 'facility', 'trainer'])
            ->where('session_date', '>=', $this->weekStart)
            ->where('session_date', '<=', $weekEnd)
            ->whereNotIn('status', ['cancelled', 'rescheduled'])
            ->when($branchId, fn ($q) => $q->whereHas('group', fn ($gq) => $gq->where('branch_id', $branchId)))
            ->when($this->programFilter, fn ($q) => $q->whereHas('group', fn ($gq) => $gq->where('training_program_id', $this->programFilter)))
            ->when($this->trainerFilter, fn ($q) => $q->where('trainer_id', $this->trainerFilter))
            ->orderBy('start_time')
            ->get();

        // Group sessions by date for the grid
        $sessionsByDate = $sessions->groupBy(fn ($s) => $s->session_date->format('Y-m-d'));

        // Programs for filter
        $programs = TrainingProgram::query()
            ->select('id', 'name_ar')
            ->when($branchId, fn ($q) => $q->where('branch_id', $branchId))
            ->orderBy('name_ar')
            ->get();

        // Trainers for filter — cascade from program
        $trainers = User::query()
            ->select('id', 'name_ar', 'name')
            ->whereHas('roles', fn ($q) => $q->whereIn('slug', ['trainer', 'head_trainer']))
            ->when($this->programFilter, fn ($q) => $q->whereIn('id',
                TrainingGroup::where('training_program_id', $this->programFilter)
                    ->whereNotNull('head_trainer_id')
                    ->pluck('head_trainer_id')
            ))
            ->orderBy('name_ar')
            ->get();

        // Assign colors per program for visual distinction
        $programColors = $this->getProgramColors($sessions);

        return view('livewire.schedule.weekly-schedule', [
            'sessionsByDate' => $sessionsByDate,
            'programs' => $programs,
            'trainers' => $trainers,
            'programColors' => $programColors,
        ]);
    }

    private function getProgramColors($sessions): array
    {
        $colors = [
            'bg-blue-100 border-blue-400 text-blue-800',
            'bg-emerald-100 border-emerald-400 text-emerald-800',
            'bg-amber-100 border-amber-400 text-amber-800',
            'bg-purple-100 border-purple-400 text-purple-800',
            'bg-rose-100 border-rose-400 text-rose-800',
            'bg-cyan-100 border-cyan-400 text-cyan-800',
            'bg-orange-100 border-orange-400 text-orange-800',
            'bg-indigo-100 border-indigo-400 text-indigo-800',
            'bg-teal-100 border-teal-400 text-teal-800',
            'bg-pink-100 border-pink-400 text-pink-800',
        ];

        $programIds = $sessions->pluck('group.training_program_id')->unique()->values();
        $map = [];

        foreach ($programIds as $index => $programId) {
            $map[$programId] = $colors[$index % count($colors)];
        }

        return $map;
    }
}
