<?php
declare(strict_types=1);

namespace App\Modules\Academies\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Academies\Models\Academy;
use App\Modules\Academies\Models\AcademyLevel;
use App\Modules\Academies\Models\AcademySchedule;
use App\Modules\Disciplines\Models\SportDiscipline;
use App\Modules\Facilities\Models\Facility;

class AcademyController extends Controller
{
    /**
     * List all academies with type filter tabs, search, and pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'             => trim((string) $request->get('q', '')),
            'academy_type'  => trim((string) $request->get('academy_type', '')),
            'discipline_id' => trim((string) $request->get('discipline_id', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = Academy::search($filters, 25, $page);

        return $this->view('Academies.Views.index', [
            'academies'    => $result['data'],
            'pagination'   => $result['pagination'],
            'filters'      => $filters,
            'academyTypes' => Academy::getAcademyTypes(),
            'disciplines'  => SportDiscipline::allActive(),
        ]);
    }

    /**
     * Show the create academy form.
     */
    public function create(Request $request): Response
    {
        return $this->view('Academies.Views.create', [
            'academyTypes' => Academy::getAcademyTypes(),
            'disciplines'  => SportDiscipline::allActive(),
        ]);
    }

    /**
     * Validate and store a new academy.
     */
    public function store(Request $request): Response
    {
        $nameAr       = trim((string) $request->post('name_ar', ''));
        $nameEn       = trim((string) $request->post('name_en', ''));
        $code         = trim((string) $request->post('code', ''));
        $disciplineId = (int) $request->post('discipline_id', 0);
        $academyType  = trim((string) $request->post('academy_type', ''));
        $descriptionAr = trim((string) $request->post('description_ar', ''));
        $sortOrder    = (int) $request->post('sort_order', 0);

        // Auto-generate code if empty
        if ($code === '') {
            $base = $nameEn ?: $nameAr;
            $code = strtoupper(preg_replace('/[^A-Z0-9]/i', '_', $base));
            $code = substr($code, 0, 25) . '_' . time() % 10000;
        }
        $code = strtoupper($code);

        // Validation
        $errors = [];
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'الاسم بالعربي مطلوب (حرفان على الأقل)';
        }
        if ($disciplineId <= 0) {
            $errors[] = 'النشاط الرياضي مطلوب';
        } else {
            $discipline = SportDiscipline::find($disciplineId);
            if (!$discipline) {
                $errors[] = 'النشاط الرياضي غير موجود';
            }
        }
        if (!array_key_exists($academyType, Academy::getAcademyTypes())) {
            $errors[] = 'نوع الأكاديمية غير صالح';
        }

        // Check unique code
        $existing = Academy::query()
            ->where('code', '=', $code)
            ->first();
        if ($existing) {
            $code = $code . '_' . bin2hex(random_bytes(2));
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/academies/create');
        }

        // Build config_json
        $config = $this->buildConfigFromRequest($request);

        $academy = Academy::create([
            'code'           => $code,
            'name_ar'        => $nameAr,
            'name_en'        => $nameEn ?: null,
            'discipline_id'  => $disciplineId,
            'academy_type'   => $academyType,
            'description_ar' => $descriptionAr ?: null,
            'config_json'    => json_encode($config, JSON_UNESCAPED_UNICODE),
            'sort_order'     => $sortOrder,
            'is_active'      => 1,
        ]);

        return $this->redirect('/academies/' . $academy->id)->withSuccess('تم إضافة الأكاديمية بنجاح');
    }

    /**
     * Show academy detail page with levels and schedules.
     */
    public function show(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $discipline = SportDiscipline::find((int) $academy->discipline_id);
        $levels = AcademyLevel::getForAcademy((int) $id);
        $schedules = AcademySchedule::getForAcademy((int) $id);

        return $this->view('Academies.Views.show', [
            'academy'      => $academy,
            'config'       => $academy->getConfig(),
            'discipline'   => $discipline,
            'levels'       => $levels,
            'schedules'    => $schedules,
            'academyTypes' => Academy::getAcademyTypes(),
            'dayLabels'    => AcademySchedule::getDayLabels(),
        ]);
    }

    /**
     * Show edit form for an academy.
     */
    public function edit(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        return $this->view('Academies.Views.edit', [
            'academy'      => $academy,
            'config'       => $academy->getConfig(),
            'academyTypes' => Academy::getAcademyTypes(),
            'disciplines'  => SportDiscipline::allActive(),
        ]);
    }

    /**
     * Validate and update an existing academy.
     */
    public function update(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $nameAr       = trim((string) $request->post('name_ar', ''));
        $nameEn       = trim((string) $request->post('name_en', ''));
        $code         = trim((string) $request->post('code', ''));
        $disciplineId = (int) $request->post('discipline_id', 0);
        $academyType  = trim((string) $request->post('academy_type', ''));
        $descriptionAr = trim((string) $request->post('description_ar', ''));
        $sortOrder    = (int) $request->post('sort_order', 0);

        // Auto-generate code if empty
        if ($code === '') {
            $base = $nameEn ?: $nameAr;
            $code = strtoupper(preg_replace('/[^A-Z0-9]/i', '_', $base));
            $code = substr($code, 0, 25) . '_' . time() % 10000;
        }
        $code = strtoupper($code);

        // Validation
        $errors = [];
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'الاسم بالعربي مطلوب (حرفان على الأقل)';
        }
        if ($disciplineId <= 0) {
            $errors[] = 'النشاط الرياضي مطلوب';
        } else {
            $discipline = SportDiscipline::find($disciplineId);
            if (!$discipline) {
                $errors[] = 'النشاط الرياضي غير موجود';
            }
        }
        if (!array_key_exists($academyType, Academy::getAcademyTypes())) {
            $errors[] = 'نوع الأكاديمية غير صالح';
        }

        // Check unique code (exclude current)
        $existing = Academy::query()
            ->where('code', '=', $code)
            ->whereRaw('`id` != ?', [(int) $id])
            ->first();
        if ($existing) {
            $errors[] = 'كود الأكاديمية مستخدم بالفعل — جرب كود مختلف';
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/academies/' . $id . '/edit');
        }

        // Build config_json
        $config = $this->buildConfigFromRequest($request);

        $academy->update([
            'code'           => $code,
            'name_ar'        => $nameAr,
            'name_en'        => $nameEn ?: null,
            'discipline_id'  => $disciplineId,
            'academy_type'   => $academyType,
            'description_ar' => $descriptionAr ?: null,
            'config_json'    => json_encode($config, JSON_UNESCAPED_UNICODE),
            'sort_order'     => $sortOrder,
        ]);

        return $this->redirect('/academies/' . $id)->withSuccess('تم تحديث الأكاديمية بنجاح');
    }

    /**
     * Toggle the is_active status of an academy.
     */
    public function toggle(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $newStatus = $academy->is_active ? 0 : 1;
        $academy->update(['is_active' => $newStatus]);

        $message = $newStatus ? 'تم تفعيل الأكاديمية' : 'تم إيقاف الأكاديمية';
        return $this->redirect('/academies/' . $id)->withSuccess($message);
    }

    /**
     * Add a level to an academy.
     */
    public function addLevel(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $nameAr      = trim((string) $request->post('name_ar', ''));
        $nameEn      = trim((string) $request->post('name_en', ''));
        $code        = trim((string) $request->post('code', ''));
        $levelOrder  = (int) $request->post('level_order', 0);
        $ageMin      = (int) $request->post('age_min', 0);
        $ageMax      = (int) $request->post('age_max', 99);
        $maxCapacity = (int) $request->post('max_capacity', 0);

        // Auto-generate code if empty
        if ($code === '') {
            $code = 'LVL_' . strtoupper(substr(preg_replace('/[^A-Z0-9]/i', '', $nameEn ?: $nameAr), 0, 10)) . '_' . $levelOrder;
        }
        $code = strtoupper($code);

        // Validation
        $errors = [];
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'اسم المستوى بالعربي مطلوب (حرفان على الأقل)';
        }

        // Ensure unique code within this academy
        $existing = AcademyLevel::query()
            ->where('academy_id', '=', (int) $id)
            ->where('code', '=', $code)
            ->first();
        if ($existing) {
            $code = $code . '_' . bin2hex(random_bytes(2));
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/academies/' . $id);
        }

        AcademyLevel::create([
            'academy_id'   => (int) $id,
            'code'         => $code,
            'name_ar'      => $nameAr,
            'name_en'      => $nameEn ?: null,
            'level_order'  => $levelOrder,
            'age_min'      => $ageMin,
            'age_max'      => $ageMax,
            'max_capacity' => $maxCapacity,
            'config_json'  => null,
            'is_active'    => 1,
        ]);

        return $this->redirect('/academies/' . $id)->withSuccess('تم إضافة المستوى بنجاح');
    }

    /**
     * Remove (delete) a level from an academy.
     */
    public function removeLevel(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $levelId = (int) $request->post('level_id', 0);
        $level = AcademyLevel::find($levelId);

        if (!$level || (int) $level->academy_id !== (int) $id) {
            return $this->redirect('/academies/' . $id)->withError('المستوى غير موجود');
        }

        $level->update(['is_active' => 0]);

        return $this->redirect('/academies/' . $id)->withSuccess('تم حذف المستوى بنجاح');
    }

    /**
     * Add a schedule to an academy.
     */
    public function addSchedule(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $levelId    = (int) $request->post('level_id', 0);
        $facilityId = (int) $request->post('facility_id', 0);
        $dayOfWeek  = (int) $request->post('day_of_week', 0);
        $startTime  = trim((string) $request->post('start_time', ''));
        $endTime    = trim((string) $request->post('end_time', ''));
        $coachName  = trim((string) $request->post('coach_name', ''));
        $season     = trim((string) $request->post('season', ''));

        // Validation
        $errors = [];
        if ($dayOfWeek < 0 || $dayOfWeek > 6) {
            $errors[] = 'يوم الأسبوع غير صالح';
        }
        if ($startTime === '') {
            $errors[] = 'وقت البدء مطلوب';
        }
        if ($endTime === '') {
            $errors[] = 'وقت الانتهاء مطلوب';
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/academies/' . $id);
        }

        AcademySchedule::create([
            'academy_id'  => (int) $id,
            'level_id'    => $levelId > 0 ? $levelId : null,
            'facility_id' => $facilityId > 0 ? $facilityId : null,
            'day_of_week' => $dayOfWeek,
            'start_time'  => $startTime,
            'end_time'    => $endTime,
            'coach_name'  => $coachName ?: null,
            'season'      => $season ?: null,
            'is_active'   => 1,
        ]);

        return $this->redirect('/academies/' . $id)->withSuccess('تم إضافة الجدول بنجاح');
    }

    /**
     * Remove (delete) a schedule from an academy.
     */
    public function removeSchedule(Request $request, string $id): Response
    {
        $academy = Academy::find((int) $id);
        if (!$academy) {
            return $this->redirect('/academies')->withError('الأكاديمية غير موجودة');
        }

        $scheduleId = (int) $request->post('schedule_id', 0);
        $schedule = AcademySchedule::find($scheduleId);

        if (!$schedule || (int) $schedule->academy_id !== (int) $id) {
            return $this->redirect('/academies/' . $id)->withError('الجدول غير موجود');
        }

        $schedule->update(['is_active' => 0]);

        return $this->redirect('/academies/' . $id)->withSuccess('تم حذف الجدول بنجاح');
    }

    /**
     * Build the config array from the request (age_min, age_max, capacity).
     */
    private function buildConfigFromRequest(Request $request): array
    {
        $config = [];

        $ageMin = $request->post('age_min');
        if ($ageMin !== null && $ageMin !== '') {
            $config['age_min'] = (int) $ageMin;
        }

        $ageMax = $request->post('age_max');
        if ($ageMax !== null && $ageMax !== '') {
            $config['age_max'] = (int) $ageMax;
        }

        $capacity = $request->post('capacity');
        if ($capacity !== null && $capacity !== '') {
            $config['capacity'] = (int) $capacity;
        }

        $requiresMedicalCert = $request->post('requires_medical_cert');
        if ($requiresMedicalCert) {
            $config['requires_medical_cert'] = true;
        }

        $guardianConsentAge = $request->post('requires_guardian_consent_under');
        if ($guardianConsentAge !== null && $guardianConsentAge !== '') {
            $config['requires_guardian_consent_under'] = (int) $guardianConsentAge;
        }

        return $config;
    }
}
