<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\Pagination;
use App\Modules\SportsActivity\Models\Program;
use App\Modules\SportsActivity\Models\Discipline;

class ProgramController extends Controller
{
    /**
     * List programs with search, filter by discipline, pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'             => trim((string) $request->get('q', '')),
            'discipline_id' => trim((string) $request->get('discipline_id', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;
        $db = App::getInstance()->db();

        $where = "p.is_archived = 0";
        $params = [];

        if ($filters['q'] !== '') {
            $where .= " AND (p.name_ar LIKE ? OR p.code LIKE ?)";
            $params[] = '%' . $filters['q'] . '%';
            $params[] = '%' . $filters['q'] . '%';
        }

        if ($filters['discipline_id'] !== '') {
            $where .= " AND p.discipline_id = ?";
            $params[] = (int) $filters['discipline_id'];
        }

        $total = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM sa_programs p WHERE {$where}", $params)['cnt'] ?? 0);
        $pagination = Pagination::paginate($total, $perPage, $page);

        $offset = ($page - 1) * $perPage;
        $programs = $db->select(
            "SELECT p.*, d.name_ar as discipline_name,
                    (SELECT COUNT(*) FROM sa_groups g WHERE g.program_id = p.id AND g.is_archived = 0) as group_count
             FROM sa_programs p
             LEFT JOIN sa_disciplines d ON d.id = p.discipline_id
             WHERE {$where}
             ORDER BY p.name_ar ASC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        $disciplines = Discipline::getActive();

        return $this->view('SportsActivity.Views.programs.index', [
            'programs'    => $programs,
            'pagination'  => $pagination,
            'filters'     => $filters,
            'disciplines' => $disciplines,
        ]);
    }

    /**
     * Show create program form.
     */
    public function create(Request $request): Response
    {
        $disciplines = Discipline::getActive();
        $db = App::getInstance()->db();
        $academies = $db->select("SELECT id, name_ar FROM sa_academies WHERE is_archived = 0 ORDER BY name_ar", []);

        return $this->view('SportsActivity.Views.programs.create', [
            'disciplines'  => $disciplines,
            'academies'    => $academies,
            'programTypes' => Program::getProgramTypeOptions(),
            'skillLevels'  => Program::getSkillLevelOptions(),
        ]);
    }

    /**
     * Validate and store a new program.
     */
    public function store(Request $request): Response
    {
        $code = strtoupper(trim((string) $request->post('code', '')));
        $nameAr = trim((string) $request->post('name_ar', ''));
        $nameEn = trim((string) $request->post('name_en', ''));
        $disciplineId = (int) $request->post('discipline_id', 0);
        $academyId = $request->post('academy_id', '') !== '' ? (int) $request->post('academy_id', 0) : null;
        $programType = trim((string) $request->post('program_type', ''));
        $ageFrom = $request->post('age_from', '') !== '' ? (int) $request->post('age_from', 0) : null;
        $ageTo = $request->post('age_to', '') !== '' ? (int) $request->post('age_to', 0) : null;
        $genderRestriction = trim((string) $request->post('gender_restriction', ''));
        $genderRestriction = in_array($genderRestriction, ['male', 'female'], true) ? $genderRestriction : null;
        $skillLevel = trim((string) $request->post('skill_level', ''));
        $sessionDuration = $request->post('session_duration_minutes', '') !== '' ? (int) $request->post('session_duration_minutes', 0) : null;
        $sessionsPerWeek = $request->post('sessions_per_week', '') !== '' ? (int) $request->post('sessions_per_week', 0) : null;
        $descriptionAr = trim((string) $request->post('description_ar', ''));
        $monthlyFeeMember = $request->post('monthly_fee_member', '') !== '' ? (float) $request->post('monthly_fee_member', 0) : 0.0;
        $monthlyFeeNonmember = $request->post('monthly_fee_nonmember', '') !== '' ? (float) $request->post('monthly_fee_nonmember', 0) : 0.0;
        $maxCapacity = $request->post('max_capacity', '') !== '' ? (int) $request->post('max_capacity', 20) : 20;
        $minCapacity = $request->post('min_capacity', '') !== '' ? (int) $request->post('min_capacity', 1) : 1;

        $errors = [];
        if ($code === '') {
            $errors[] = 'كود البرنامج مطلوب';
        }
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'اسم البرنامج بالعربي مطلوب (حرفان على الأقل)';
        }
        if ($disciplineId === 0) {
            $errors[] = 'النشاط الرياضي (اللعبة) مطلوب';
        }
        if ($monthlyFeeMember < 0) {
            $errors[] = 'رسوم الأعضاء لا يمكن أن تكون سالبة';
        }
        if ($monthlyFeeNonmember < 0) {
            $errors[] = 'رسوم غير الأعضاء لا يمكن أن تكون سالبة';
        }
        if ($maxCapacity < 1) {
            $errors[] = 'الحد الأقصى للسعة يجب أن يكون 1 على الأقل';
        }
        if ($minCapacity > $maxCapacity) {
            $errors[] = 'الحد الأدنى لا يمكن أن يتجاوز الأقصى';
        }

        // Check unique code
        if ($code !== '') {
            $db = App::getInstance()->db();
            $existing = $db->selectOne("SELECT id FROM sa_programs WHERE code = ?", [$code]);
            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('/sa/programs/create');
        }

        $program = Program::create([
            'code'                    => $code,
            'name_ar'                 => $nameAr,
            'name_en'                 => $nameEn ?: null,
            'discipline_id'           => $disciplineId,
            'academy_id'              => $academyId,
            'program_type'            => $programType ?: null,
            'age_from'                => $ageFrom,
            'age_to'                  => $ageTo,
            'gender_restriction'      => $genderRestriction,
            'skill_level'             => $skillLevel ?: null,
            'session_duration_minutes' => $sessionDuration,
            'sessions_per_week'       => $sessionsPerWeek,
            'monthly_fee_member'      => $monthlyFeeMember,
            'monthly_fee_nonmember'   => $monthlyFeeNonmember,
            'max_capacity'            => $maxCapacity,
            'min_capacity'            => $minCapacity,
            'description_ar'          => $descriptionAr ?: null,
            'is_active'               => 1,
        ]);

        $db = App::getInstance()->db();
        $coach = $db->selectOne(
            "SELECT c.id FROM sa_coaches c
             INNER JOIN sa_coach_disciplines cd ON cd.coach_id = c.id
             WHERE cd.discipline_id = ? AND c.is_active = 1 AND c.is_archived = 0
             LIMIT 1",
            [$disciplineId]
        );
        if (!$coach) {
            $coach = $db->selectOne("SELECT id FROM sa_coaches WHERE is_active = 1 AND is_archived = 0 LIMIT 1");
        }

        if ($coach) {
            $groupCode = $code . '-G1';
            $existing = $db->selectOne("SELECT id FROM sa_groups WHERE code = ?", [$groupCode]);
            if (!$existing) {
                $db->insert('sa_groups', [
                    'code'          => $groupCode,
                    'name_ar'       => $nameAr . ' - مجموعة 1',
                    'name_en'       => $nameEn ? $nameEn . ' - Group 1' : null,
                    'program_id'    => (int) $program->id,
                    'coach_id'      => (int) $coach['id'],
                    'min_capacity'  => $minCapacity,
                    'max_capacity'  => $maxCapacity,
                    'current_count' => 0,
                    'is_full'       => 0,
                    'status'        => 'active',
                    'created_at'    => date('Y-m-d H:i:s'),
                    'updated_at'    => date('Y-m-d H:i:s'),
                ]);
            }
        }

        return $this->redirect('/sa/programs/' . $program->id)->withSuccess('تم إضافة البرنامج بنجاح' . ($coach ? ' وتم إنشاء مجموعة افتراضية' : ''));
    }

    /**
     * Show program detail page with groups list.
     */
    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $program = $db->selectOne(
            "SELECT p.*, d.name_ar as discipline_name, a.name_ar as academy_name
             FROM sa_programs p
             LEFT JOIN sa_disciplines d ON d.id = p.discipline_id
             LEFT JOIN sa_academies a ON a.id = p.academy_id
             WHERE p.id = ? AND p.is_archived = 0",
            [(int) $id]
        );

        if (!$program) {
            return $this->redirect('/sa/programs')->withError('البرنامج غير موجود');
        }

        $groups = $db->select(
            "SELECT g.*, c.full_name_ar as coach_name
             FROM sa_groups g
             LEFT JOIN sa_coaches c ON c.id = g.coach_id
             WHERE g.program_id = ? AND g.is_archived = 0
             ORDER BY g.name_ar ASC",
            [(int) $id]
        );

        return $this->view('SportsActivity.Views.programs.show', [
            'program'      => $program,
            'groups'       => $groups,
            'programTypes' => Program::getProgramTypeOptions(),
            'skillLevels'  => Program::getSkillLevelOptions(),
        ]);
    }

    /**
     * Show edit form for a program.
     */
    public function edit(Request $request, string $id): Response
    {
        $program = Program::find((int) $id);
        if (!$program) {
            return $this->redirect('/sa/programs')->withError('البرنامج غير موجود');
        }

        $disciplines = Discipline::getActive();
        $db = App::getInstance()->db();
        $academies = $db->select("SELECT id, name_ar FROM sa_academies WHERE is_archived = 0 ORDER BY name_ar", []);

        return $this->view('SportsActivity.Views.programs.edit', [
            'program'      => $program,
            'disciplines'  => $disciplines,
            'academies'    => $academies,
            'programTypes' => Program::getProgramTypeOptions(),
            'skillLevels'  => Program::getSkillLevelOptions(),
        ]);
    }

    /**
     * Validate and update an existing program.
     */
    public function update(Request $request, string $id): Response
    {
        $program = Program::find((int) $id);
        if (!$program) {
            return $this->redirect('/sa/programs')->withError('البرنامج غير موجود');
        }

        $code = strtoupper(trim((string) $request->post('code', '')));
        $nameAr = trim((string) $request->post('name_ar', ''));
        $nameEn = trim((string) $request->post('name_en', ''));
        $disciplineId = (int) $request->post('discipline_id', 0);
        $academyId = $request->post('academy_id', '') !== '' ? (int) $request->post('academy_id', 0) : null;
        $programType = trim((string) $request->post('program_type', ''));
        $ageFrom = $request->post('age_from', '') !== '' ? (int) $request->post('age_from', 0) : null;
        $ageTo = $request->post('age_to', '') !== '' ? (int) $request->post('age_to', 0) : null;
        $genderRestriction = trim((string) $request->post('gender_restriction', ''));
        $genderRestriction = in_array($genderRestriction, ['male', 'female'], true) ? $genderRestriction : null;
        $skillLevel = trim((string) $request->post('skill_level', ''));
        $sessionDuration = $request->post('session_duration_minutes', '') !== '' ? (int) $request->post('session_duration_minutes', 0) : null;
        $sessionsPerWeek = $request->post('sessions_per_week', '') !== '' ? (int) $request->post('sessions_per_week', 0) : null;
        $descriptionAr = trim((string) $request->post('description_ar', ''));
        $monthlyFeeMember = $request->post('monthly_fee_member', '') !== '' ? (float) $request->post('monthly_fee_member', 0) : 0.0;
        $monthlyFeeNonmember = $request->post('monthly_fee_nonmember', '') !== '' ? (float) $request->post('monthly_fee_nonmember', 0) : 0.0;
        $maxCapacity = $request->post('max_capacity', '') !== '' ? (int) $request->post('max_capacity', 20) : 20;
        $minCapacity = $request->post('min_capacity', '') !== '' ? (int) $request->post('min_capacity', 1) : 1;

        $errors = [];
        if ($code === '') {
            $errors[] = 'كود البرنامج مطلوب';
        }
        if ($nameAr === '' || mb_strlen($nameAr) < 2) {
            $errors[] = 'اسم البرنامج بالعربي مطلوب (حرفان على الأقل)';
        }
        if ($disciplineId === 0) {
            $errors[] = 'النشاط الرياضي (اللعبة) مطلوب';
        }
        if ($monthlyFeeMember < 0) {
            $errors[] = 'رسوم الأعضاء لا يمكن أن تكون سالبة';
        }
        if ($monthlyFeeNonmember < 0) {
            $errors[] = 'رسوم غير الأعضاء لا يمكن أن تكون سالبة';
        }
        if ($maxCapacity < 1) {
            $errors[] = 'الحد الأقصى للسعة يجب أن يكون 1 على الأقل';
        }
        if ($minCapacity > $maxCapacity) {
            $errors[] = 'الحد الأدنى لا يمكن أن يتجاوز الأقصى';
        }

        // Check unique code (exclude current)
        if ($code !== '') {
            $db = App::getInstance()->db();
            $existing = $db->selectOne("SELECT id FROM sa_programs WHERE code = ? AND id != ?", [$code, (int) $id]);
            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('/sa/programs/' . $id . '/edit');
        }

        $program->update([
            'code'                    => $code,
            'name_ar'                 => $nameAr,
            'name_en'                 => $nameEn ?: null,
            'discipline_id'           => $disciplineId,
            'academy_id'              => $academyId,
            'program_type'            => $programType ?: null,
            'age_from'                => $ageFrom,
            'age_to'                  => $ageTo,
            'gender_restriction'      => $genderRestriction,
            'skill_level'             => $skillLevel ?: null,
            'session_duration_minutes' => $sessionDuration,
            'sessions_per_week'       => $sessionsPerWeek,
            'monthly_fee_member'      => $monthlyFeeMember,
            'monthly_fee_nonmember'   => $monthlyFeeNonmember,
            'max_capacity'            => $maxCapacity,
            'min_capacity'            => $minCapacity,
            'description_ar'          => $descriptionAr ?: null,
        ]);

        // Sync capacity to all active groups of this program
        $db = App::getInstance()->db();
        $db->query(
            "UPDATE sa_groups SET max_capacity = ?, is_full = IF(current_count >= ?, 1, 0), updated_at = NOW()
             WHERE program_id = ? AND status = 'active' AND is_archived = 0",
            [$maxCapacity, $maxCapacity, (int) $id]
        );

        return $this->redirect('/sa/programs/' . $id)->withSuccess('تم تحديث البرنامج بنجاح');
    }
}
