<?php

namespace Database\Seeders;

use App\Domain\Attendance\Enums\AttendanceStatus;
use App\Domain\Attendance\Models\AttendanceRecord;
use App\Domain\Identity\Models\Branch;
use App\Domain\Identity\Models\Person;
use App\Domain\Identity\Models\Role;
use App\Domain\Participant\Models\Participant;
use App\Domain\Scheduling\Models\Assignment;
use App\Domain\Shared\Models\Academy;
use App\Domain\Training\Models\Activity;
use App\Domain\Training\Models\Enrollment;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingProgram;
use App\Domain\Training\Models\TrainingSession;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

/**
 * Seeds a complete trainer + groups + today's sessions + participants + attendance records.
 *
 * Trainer login: trainer@demo.com / Demo1234#
 *
 * Idempotent — safe to re-run.
 */
class TrainerAttendanceDemoSeeder extends Seeder
{
    public function run(): void
    {
        $academy = Academy::first();
        if (!$academy) {
            $this->command->error('No academy found — run DatabaseSeeder first.');
            return;
        }

        app()->instance('current_academy', $academy);

        $admin = User::where('academy_id', $academy->id)
            ->where('is_super_admin', true)
            ->first()
            ?? User::where('academy_id', $academy->id)->first();

        if (!$admin) {
            $this->command->error('No admin user found — run DatabaseSeeder first.');
            return;
        }

        $branch       = $this->ensureBranch($academy, $admin);
        $activity     = $this->ensureActivity($academy, $admin);
        $program      = $this->ensureProgram($academy, $branch, $activity, $admin);
        $trainer      = $this->ensureTrainerUser($academy, $branch, $admin);
        [$youth, $junior] = $this->ensureGroups($academy, $branch, $program, $trainer, $admin);
        $this->ensureAssignment($academy, $trainer, $youth, $admin);
        $this->ensureAssignment($academy, $trainer, $junior, $admin);
        $this->ensureParticipants($academy, $branch, $activity, $admin, $youth, $junior);
        $this->ensureTodaysSessions($academy, $trainer, $youth, $junior);

        $this->command->info('');
        $this->command->info('╔═══════════════════════════════════════════════════╗');
        $this->command->info('║         Trainer Demo Seed — DONE                  ║');
        $this->command->info('╠═══════════════════════════════════════════════════╣');
        $this->command->info('║  Login  : trainer@demo.com                        ║');
        $this->command->info('║  Pass   : Demo1234#                               ║');
        $this->command->info('║  Branch : ' . str_pad($branch->name, 41) . '║');
        $this->command->info('║  Groups : شباب المدرسين  +  ناشئين المدرسين       ║');
        $this->command->info('║  Go to  : /trainer  then click a session          ║');
        $this->command->info('╚═══════════════════════════════════════════════════╝');
    }

    // ─── Branch ───────────────────────────────────────────────────────────────

    private function ensureBranch(Academy $academy, User $admin): Branch
    {
        return Branch::where('academy_id', $academy->id)->first()
            ?? Branch::create([
                'academy_id' => $academy->id,
                'name'       => 'Main Branch',
                'name_ar'    => 'الفرع الرئيسي',
                'code'       => 'MAIN',
                'is_main'    => true,
                'is_active'  => true,
            ]);
    }

    // ─── Activity ─────────────────────────────────────────────────────────────

    private function ensureActivity(Academy $academy, User $admin): Activity
    {
        return Activity::firstOrCreate(
            ['academy_id' => $academy->id, 'slug' => 'football'],
            [
                'academy_id' => $academy->id,
                'name'       => 'Football',
                'name_ar'    => 'كرة القدم',
                'slug'       => 'football',
                'is_active'  => true,
                'sort_order' => 1,
            ]
        );
    }

    // ─── Program ──────────────────────────────────────────────────────────────

    private function ensureProgram(Academy $academy, Branch $branch, Activity $activity, User $admin): TrainingProgram
    {
        return TrainingProgram::firstOrCreate(
            ['academy_id' => $academy->id, 'slug' => 'football-youth-demo'],
            [
                'academy_id'               => $academy->id,
                'activity_id'              => $activity->id,
                'branch_id'                => $branch->id,
                'name'                     => 'Football Youth Program',
                'name_ar'                  => 'برنامج كرة القدم للشباب',
                'slug'                     => 'football-youth-demo',
                'sessions_per_week'        => 3,
                'session_duration_minutes' => 90,
                'total_sessions'           => 48,
                'program_duration_weeks'   => 16,
                'min_participants'         => 5,
                'max_participants'         => 20,
                'allow_waitlist'           => true,
                'registration_open'        => true,
                'status'                   => 'active',
                'created_by'               => $admin->id,
            ]
        );
    }

    // ─── Trainer User ─────────────────────────────────────────────────────────

    private function ensureTrainerUser(Academy $academy, Branch $branch, User $admin): User
    {
        $trainerRole = Role::where('academy_id', $academy->id)
            ->where('slug', 'trainer')
            ->first();

        $trainer = User::firstOrCreate(
            ['email' => 'trainer@demo.com'],
            [
                'academy_id' => $academy->id,
                'name'       => 'Ahmed Demo Trainer',
                'name_ar'    => 'أحمد المدرب التجريبي',
                'email'      => 'trainer@demo.com',
                'password'   => Hash::make('Demo1234#'),
                'status'     => 'active',
                'role_id'    => $trainerRole?->id,
            ]
        );

        if (!$trainer->person_id) {
            $person = Person::firstOrCreate(
                ['academy_id' => $academy->id, 'phone' => '01000000001'],
                [
                    'academy_id' => $academy->id,
                    'name'       => 'Ahmed Demo Trainer',
                    'name_ar'    => 'أحمد المدرب التجريبي',
                    'email'      => 'trainer@demo.com',
                    'phone'      => '01000000001',
                    'gender'     => 'male',
                    'created_by' => $admin->id,
                ]
            );
            $trainer->update(['person_id' => $person->id]);
        }

        if ($trainerRole) {
            $linked = DB::table('role_user')
                ->where('user_id', $trainer->id)
                ->where('role_id', $trainerRole->id)
                ->exists();

            if (!$linked) {
                DB::table('role_user')->insert([
                    'user_id'    => $trainer->id,
                    'role_id'    => $trainerRole->id,
                    'branch_id'  => $branch->id,
                    'created_at' => now(),
                ]);
            }
        }

        return $trainer;
    }

    // ─── Groups ───────────────────────────────────────────────────────────────

    private function ensureGroups(Academy $academy, Branch $branch, TrainingProgram $program, User $trainer, User $admin): array
    {
        $shared = [
            'academy_id'          => $academy->id,
            'training_program_id' => $program->id,
            'branch_id'           => $branch->id,
            'head_trainer_id'     => $trainer->id,
            'max_capacity'        => 15,
            'current_count'       => 4,
            'waitlist_count'      => 0,
            'season'              => '2025-2026',
            'start_date'          => now()->startOfMonth()->toDateString(),
            'end_date'            => now()->addMonths(4)->toDateString(),
            'status'              => 'active',
            'created_by'          => $admin->id,
        ];

        $youth = TrainingGroup::firstOrCreate(
            ['academy_id' => $academy->id, 'code' => 'DEMO-YOUTH'],
            $shared + ['name' => 'Youth Demo Group', 'name_ar' => 'شباب المدرسين', 'code' => 'DEMO-YOUTH']
        );

        $junior = TrainingGroup::firstOrCreate(
            ['academy_id' => $academy->id, 'code' => 'DEMO-JNR'],
            $shared + ['name' => 'Junior Demo Group', 'name_ar' => 'ناشئين المدرسين', 'code' => 'DEMO-JNR']
        );

        return [$youth, $junior];
    }

    // ─── Assignment ───────────────────────────────────────────────────────────

    private function ensureAssignment(Academy $academy, User $trainer, TrainingGroup $group, User $admin): void
    {
        $exists = Assignment::where('academy_id', $academy->id)
            ->where('user_id', $trainer->id)
            ->where('assignable_type', TrainingGroup::class)
            ->where('assignable_id', $group->id)
            ->where('status', 'active')
            ->exists();

        if ($exists) {
            return;
        }

        Assignment::create([
            'academy_id'      => $academy->id,
            'user_id'         => $trainer->id,
            'assignable_type' => TrainingGroup::class,
            'assignable_id'   => $group->id,
            'role_label'      => 'head trainer',
            'scope'           => 'full',
            'status'          => 'active',
            'is_primary'      => true,
            'start_date'      => now()->startOfMonth()->toDateString(),
            'created_by'      => $admin->id,
        ]);
    }

    // ─── Participants ─────────────────────────────────────────────────────────

    private function ensureParticipants(Academy $academy, Branch $branch, Activity $activity, User $admin, TrainingGroup ...$groups): void
    {
        $byGroup = [
            [
                ['name' => 'Mohamed Sayed',   'name_ar' => 'محمد سيد',     'phone' => '01011111101', 'dob' => '2008-03-15'],
                ['name' => 'Omar Hassan',     'name_ar' => 'عمر حسن',      'phone' => '01011111102', 'dob' => '2007-07-22'],
                ['name' => 'Karim Ali',       'name_ar' => 'كريم علي',     'phone' => '01011111103', 'dob' => '2008-11-01'],
                ['name' => 'Youssef Ibrahim', 'name_ar' => 'يوسف إبراهيم', 'phone' => '01011111104', 'dob' => '2009-01-30'],
            ],
            [
                ['name' => 'Ahmed Ramadan',  'name_ar' => 'أحمد رمضان',   'phone' => '01011111105', 'dob' => '2011-05-10'],
                ['name' => 'Hassan Mostafa', 'name_ar' => 'حسن مصطفى',    'phone' => '01011111106', 'dob' => '2010-09-18'],
                ['name' => 'Amr Khaled',     'name_ar' => 'عمرو خالد',    'phone' => '01011111107', 'dob' => '2011-12-25'],
                ['name' => 'Ziad Nasser',    'name_ar' => 'زياد ناصر',    'phone' => '01011111108', 'dob' => '2012-02-14'],
            ],
        ];

        foreach ($groups as $idx => $group) {
            $pNum = 1001 + ($idx * 100);

            foreach ($byGroup[$idx] as $data) {
                $person = Person::firstOrCreate(
                    ['academy_id' => $academy->id, 'phone' => $data['phone']],
                    [
                        'academy_id'    => $academy->id,
                        'name'          => $data['name'],
                        'name_ar'       => $data['name_ar'],
                        'phone'         => $data['phone'],
                        'date_of_birth' => $data['dob'],
                        'gender'        => 'male',
                        'created_by'    => $admin->id,
                    ]
                );

                $participant = Participant::firstOrCreate(
                    ['academy_id' => $academy->id, 'person_id' => $person->id],
                    [
                        'academy_id'          => $academy->id,
                        'branch_id'           => $branch->id,
                        'person_id'           => $person->id,
                        'participant_number'  => 'P-' . $pNum++,
                        'registration_date'   => now()->subMonths(2)->toDateString(),
                        'primary_activity_id' => $activity->id,
                        'status'              => 'active',
                        'created_by'          => $admin->id,
                    ]
                );

                Enrollment::firstOrCreate(
                    [
                        'academy_id'        => $academy->id,
                        'participant_id'    => $participant->id,
                        'training_group_id' => $group->id,
                    ],
                    [
                        'academy_id'           => $academy->id,
                        'participant_id'       => $participant->id,
                        'training_group_id'    => $group->id,
                        'training_program_id'  => $group->training_program_id,
                        'enrollment_date'      => now()->subMonths(2)->toDateString(),
                        'start_date'           => now()->subMonths(2)->toDateString(),
                        'status'               => 'active',
                        'enrolled_by'          => $admin->id,
                    ]
                );
            }
        }
    }

    // ─── Today's Sessions + Attendance Records ────────────────────────────────

    private function ensureTodaysSessions(Academy $academy, User $trainer, TrainingGroup $youth, TrainingGroup $junior): void
    {
        $today = now()->toDateString();

        $configs = [
            ['group' => $youth,  'start' => '09:00:00', 'end' => '10:30:00'],
            ['group' => $junior, 'start' => '11:00:00', 'end' => '12:30:00'],
        ];

        foreach ($configs as $cfg) {
            /** @var TrainingGroup $group */
            $group = $cfg['group'];

            $session = TrainingSession::firstOrCreate(
                [
                    'academy_id'        => $academy->id,
                    'training_group_id' => $group->id,
                    'session_date'      => $today,
                    'start_time'        => $cfg['start'],
                ],
                [
                    'academy_id'           => $academy->id,
                    'training_group_id'    => $group->id,
                    'trainer_id'           => $trainer->id,
                    'session_date'         => $today,
                    'start_time'           => $cfg['start'],
                    'end_time'             => $cfg['end'],
                    'session_number'       => 1,
                    'status'               => 'scheduled',
                    'expected_participants' => 4,
                ]
            );

            $enrollments = Enrollment::where('academy_id', $academy->id)
                ->where('training_group_id', $group->id)
                ->where('status', 'active')
                ->with('participant')
                ->get();

            foreach ($enrollments as $enrollment) {
                $participant = $enrollment->participant;
                if (!$participant) {
                    continue;
                }

                AttendanceRecord::firstOrCreate(
                    [
                        'academy_id'          => $academy->id,
                        'training_session_id' => $session->id,
                        'subject_type'        => Participant::class,
                        'subject_id'          => $participant->id,
                    ],
                    [
                        'academy_id'          => $academy->id,
                        'training_session_id' => $session->id,
                        'subject_type'        => Participant::class,
                        'subject_id'          => $participant->id,
                        'status'              => AttendanceStatus::Expected,
                        'is_auto_generated'   => true,
                        'is_flagged'          => false,
                    ]
                );
            }
        }
    }
}
