<?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\Coach;
use App\Modules\SportsActivity\Models\Discipline;
use App\Modules\Members\Services\NationalIdParser;

class CoachController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();

        $search = trim((string) $request->get('q', ''));
        $disciplineFilter = trim((string) $request->get('discipline_id', ''));
        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;

        $where = ['c.is_archived = 0'];
        $params = [];
        $joins = '';

        if ($search !== '') {
            $where[] = '(c.full_name_ar LIKE ? OR c.full_name_en LIKE ? OR c.national_id LIKE ? OR c.code LIKE ?)';
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
            $params[] = "%{$search}%";
        }

        if ($disciplineFilter !== '') {
            $joins = 'INNER JOIN sa_coach_disciplines cdf ON cdf.coach_id = c.id AND cdf.discipline_id = ?';
            $params[] = (int) $disciplineFilter;
        }

        $whereSql = implode(' AND ', $where);

        $total = (int) $db->selectOne(
            "SELECT COUNT(DISTINCT c.id) as cnt FROM sa_coaches c {$joins} WHERE {$whereSql}",
            $params
        )['cnt'];

        $pagination = Pagination::paginate($total, $perPage, $page);
        $offset = ($page - 1) * $perPage;

        $coaches = $db->select(
            "SELECT c.*,
                    GROUP_CONCAT(d.name_ar SEPARATOR '، ') as discipline_names
             FROM sa_coaches c
             {$joins}
             LEFT JOIN sa_coach_disciplines cd ON cd.coach_id = c.id
             LEFT JOIN sa_disciplines d ON d.id = cd.discipline_id
             WHERE {$whereSql}
             GROUP BY c.id
             ORDER BY c.created_at DESC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        $disciplines = Discipline::getActive();

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

    public function create(Request $request): Response
    {
        $db = App::getInstance()->db();
        $disciplines = Discipline::getActive();
        $employmentTypes = Coach::getEmploymentTypeOptions();
        $paymentModels = Coach::getPaymentModelOptions();
        $coachTypes = Coach::getCoachTypeOptions();
        $academies = $db->select(
            "SELECT id, name_ar FROM sa_academies WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('SportsActivity.Views.coaches.create', [
            'disciplines'     => $disciplines,
            'employmentTypes' => $employmentTypes,
            'paymentModels'   => $paymentModels,
            'coachTypes'      => $coachTypes,
            'academies'       => $academies,
        ]);
    }

    public function store(Request $request): Response
    {
        $db = App::getInstance()->db();

        $code = strtoupper(trim((string) $request->post('code', '')));
        $fullNameAr = trim((string) $request->post('full_name_ar', ''));
        $fullNameEn = trim((string) $request->post('full_name_en', ''));
        $nationalId = preg_replace('/\D/', '', trim((string) $request->post('national_id', '')));
        $phone = trim((string) $request->post('phone', ''));
        $email = trim((string) $request->post('email', ''));
        $dateOfBirth = trim((string) $request->post('date_of_birth', ''));
        $gender = trim((string) $request->post('gender', ''));
        $employmentType = trim((string) $request->post('employment_type', ''));
        $paymentModel = trim((string) $request->post('payment_model', ''));
        $hourlyRate = trim((string) $request->post('hourly_rate', ''));
        $sessionRate = trim((string) $request->post('session_rate', ''));
        $monthlyRate = trim((string) $request->post('monthly_rate', ''));
        $maxGroups = trim((string) $request->post('max_groups', ''));
        $bioAr = trim((string) $request->post('bio_ar', ''));
        $coachType = trim((string) $request->post('coach_type', 'independent'));

        if (!array_key_exists($coachType, Coach::getCoachTypeOptions())) {
            $coachType = 'independent';
        }

        // Validation
        $errors = [];
        if ($code === '') {
            $errors[] = 'كود المدرب مطلوب';
        } elseif (mb_strlen($code) > 30) {
            $errors[] = 'كود المدرب يجب ألا يتجاوز 30 حرف';
        } elseif (Coach::findByCode($code) !== null) {
            $errors[] = 'كود المدرب "' . $code . '" مستخدم بالفعل — اختر كود آخر';
        }
        if ($fullNameAr === '') {
            $errors[] = 'الاسم بالعربي مطلوب';
        } elseif (mb_strlen($fullNameAr) > 300) {
            $errors[] = 'الاسم بالعربي يجب ألا يتجاوز 300 حرف';
        }
        if ($employmentType === '') {
            $errors[] = 'نوع التوظيف مطلوب';
        }
        if ($coachType !== 'academy' && $paymentModel === '') {
            $errors[] = 'نموذج الدفع مطلوب للمدربين غير التابعين لأكاديمية';
        }
        if ($coachType === 'academy' && !(int) $request->post('academy_id', 0)) {
            $errors[] = 'يجب اختيار الأكاديمية لمدرب أكاديمية';
        }
        if ($nationalId !== '' && strlen($nationalId) !== 14) {
            $errors[] = 'الرقم القومي يجب أن يكون 14 رقم بالضبط';
        }
        if ($nationalId !== '' && strlen($nationalId) === 14) {
            $existingCoach = $db->selectOne("SELECT id, full_name_ar FROM sa_coaches WHERE national_id = ? AND is_archived = 0", [$nationalId]);
            if ($existingCoach) {
                $errors[] = 'الرقم القومي مسجل بالفعل للمدرب: ' . ($existingCoach['full_name_ar'] ?? '');
            }
        }
        if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors[] = 'صيغة البريد الإلكتروني غير صحيحة';
        }

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

        // Parse NID for DOB/gender
        if ($nationalId !== '' && strlen($nationalId) === 14) {
            $parsed = NationalIdParser::parse($nationalId);
            if ($parsed['is_valid']) {
                if ($parsed['dob']) $dateOfBirth = $parsed['dob'];
                if ($parsed['gender']) $gender = $parsed['gender'];
            }
        }

        $academyId = $coachType === 'academy' ? ((int) $request->post('academy_id', 0) ?: null) : null;

        $coach = Coach::create([
            'code'            => $code,
            'full_name_ar'    => $fullNameAr,
            'full_name_en'    => $fullNameEn ?: null,
            'national_id'     => $nationalId ?: null,
            'phone'           => $phone ?: null,
            'email'           => $email ?: null,
            'date_of_birth'   => $dateOfBirth ?: null,
            'gender'          => $gender ?: null,
            'employment_type' => $employmentType,
            'coach_type'      => $coachType,
            'academy_id'      => $academyId,
            'payment_model'   => $coachType === 'academy' ? 'salary' : ($paymentModel ?: 'per_session'),
            'hourly_rate'     => $coachType === 'academy' ? null : ($hourlyRate !== '' ? (float) $hourlyRate : null),
            'session_rate'    => $coachType === 'academy' ? null : ($sessionRate !== '' ? (float) $sessionRate : null),
            'monthly_rate'    => $coachType === 'academy' ? null : ($monthlyRate !== '' ? (float) $monthlyRate : null),
            'max_groups'      => $maxGroups !== '' ? max(1, (int) $maxGroups) : 10,
            'bio_ar'          => $bioAr ?: null,
            'is_active'       => 1,
            'branch_id'       => App::getInstance()->session()->get('branch_id', 1),
        ]);

        $this->syncDisciplines($db, (int) $coach->id, $request);

        return $this->redirect('/sa/coaches')->withSuccess('تم إضافة المدرب "' . $fullNameAr . '" بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $coach = $db->selectOne(
            "SELECT c.*, a.name_ar as academy_name
             FROM sa_coaches c
             LEFT JOIN sa_academies a ON a.id = c.academy_id
             WHERE c.id = ? AND c.is_archived = 0",
            [(int) $id]
        );

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

        $disciplines = $db->select(
            "SELECT cd.*, d.name_ar as discipline_name, d.code as discipline_code
             FROM sa_coach_disciplines cd
             JOIN sa_disciplines d ON d.id = cd.discipline_id
             WHERE cd.coach_id = ?
             ORDER BY cd.specialization_level = 'primary' DESC",
            [(int) $id]
        );

        $employmentTypes = Coach::getEmploymentTypeOptions();
        $paymentModels = Coach::getPaymentModelOptions();

        $weeklySchedule = $db->select(
            "SELECT gs.day_of_week, gs.start_time, gs.end_time,
                    g.id as group_id, g.name_ar as group_name,
                    fu.name_ar as unit_name, f.name_ar as facility_name
             FROM sa_group_schedule gs
             INNER JOIN sa_groups g ON g.id = gs.group_id AND g.status = 'active' AND g.is_archived = 0
             INNER JOIN sa_facility_units fu ON fu.id = gs.facility_unit_id
             INNER JOIN sa_facilities f ON f.id = fu.facility_id
             WHERE g.coach_id = ? AND gs.is_active = 1
             ORDER BY gs.day_of_week ASC, gs.start_time ASC",
            [(int) $id]
        );

        return $this->view('SportsActivity.Views.coaches.show', [
            'coach'           => $coach,
            'disciplines'     => $disciplines,
            'employmentTypes' => $employmentTypes,
            'paymentModels'   => $paymentModels,
            'weeklySchedule'  => $weeklySchedule,
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $coach = $db->selectOne(
            "SELECT * FROM sa_coaches WHERE id = ? AND is_archived = 0",
            [(int) $id]
        );

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

        $coachDisciplines = $db->select(
            "SELECT cd.discipline_id, cd.specialization_level
             FROM sa_coach_disciplines cd
             WHERE cd.coach_id = ?",
            [(int) $id]
        );

        $disciplines = Discipline::getActive();
        $employmentTypes = Coach::getEmploymentTypeOptions();
        $paymentModels = Coach::getPaymentModelOptions();
        $coachTypes = Coach::getCoachTypeOptions();
        $academies = $db->select(
            "SELECT id, name_ar FROM sa_academies WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('SportsActivity.Views.coaches.edit', [
            'coach'            => $coach,
            'coachDisciplines' => $coachDisciplines,
            'disciplines'      => $disciplines,
            'employmentTypes'  => $employmentTypes,
            'paymentModels'    => $paymentModels,
            'coachTypes'       => $coachTypes,
            'academies'        => $academies,
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $coach = $db->selectOne(
            "SELECT * FROM sa_coaches WHERE id = ? AND is_archived = 0",
            [(int) $id]
        );

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

        $code = trim((string) $request->post('code', ''));
        $fullNameAr = trim((string) $request->post('full_name_ar', ''));
        $fullNameEn = trim((string) $request->post('full_name_en', ''));
        $nationalId = trim((string) $request->post('national_id', ''));
        $phone = trim((string) $request->post('phone', ''));
        $email = trim((string) $request->post('email', ''));
        $dateOfBirth = trim((string) $request->post('date_of_birth', ''));
        $gender = trim((string) $request->post('gender', ''));
        $employmentType = trim((string) $request->post('employment_type', ''));
        $paymentModel = trim((string) $request->post('payment_model', ''));
        $hourlyRate = trim((string) $request->post('hourly_rate', ''));
        $sessionRate = trim((string) $request->post('session_rate', ''));
        $monthlyRate = trim((string) $request->post('monthly_rate', ''));
        $maxGroups = trim((string) $request->post('max_groups', ''));
        $bioAr = trim((string) $request->post('bio_ar', ''));

        // Validation
        $errors = [];
        if ($code === '') {
            $errors[] = 'كود المدرب مطلوب';
        } elseif (mb_strlen($code) > 30) {
            $errors[] = 'كود المدرب يجب ألا يتجاوز 30 حرف';
        }
        if ($fullNameAr === '') {
            $errors[] = 'الاسم بالعربي مطلوب';
        } elseif (mb_strlen($fullNameAr) > 300) {
            $errors[] = 'الاسم بالعربي يجب ألا يتجاوز 300 حرف';
        }
        if ($employmentType === '') {
            $errors[] = 'نوع التوظيف مطلوب';
        }
        $coachType = trim((string) $request->post('coach_type', 'independent'));
        if (!array_key_exists($coachType, Coach::getCoachTypeOptions())) {
            $coachType = 'independent';
        }
        if ($coachType !== 'academy' && $paymentModel === '') {
            $errors[] = 'نموذج الدفع مطلوب';
        }
        if ($code !== '' && $code !== $coach['code']) {
            $existing = Coach::findByCode($code);
            if ($existing !== null && (int) $existing->id !== (int) $id) {
                $errors[] = 'كود المدرب مستخدم بالفعل';
            }
        }

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

        if ($nationalId !== '' && strlen($nationalId) === 14) {
            $parsed = NationalIdParser::parse($nationalId);
            if ($parsed['is_valid']) {
                $dateOfBirth = $parsed['dob'];
                $gender = $parsed['gender'];
            }
        }

        $academyId = $coachType === 'academy' ? ((int) $request->post('academy_id', 0) ?: null) : null;

        $db->update('sa_coaches', [
            'code'            => $code,
            'full_name_ar'    => $fullNameAr,
            'full_name_en'    => $fullNameEn ?: null,
            'national_id'     => $nationalId ?: null,
            'phone'           => $phone ?: null,
            'email'           => $email ?: null,
            'date_of_birth'   => $dateOfBirth ?: null,
            'gender'          => $gender ?: null,
            'employment_type' => $employmentType,
            'coach_type'      => $coachType,
            'academy_id'      => $academyId,
            'payment_model'   => $coachType === 'academy' ? 'salary' : ($paymentModel ?: 'per_session'),
            'hourly_rate'     => $coachType === 'academy' ? null : ($hourlyRate !== '' ? (float) $hourlyRate : null),
            'session_rate'    => $coachType === 'academy' ? null : ($sessionRate !== '' ? (float) $sessionRate : null),
            'monthly_rate'    => $coachType === 'academy' ? null : ($monthlyRate !== '' ? (float) $monthlyRate : null),
            'max_groups'      => $maxGroups !== '' ? (int) $maxGroups : 10,
            'bio_ar'          => $bioAr ?: null,
            'updated_at'      => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        // Sync disciplines
        $this->syncDisciplines($db, (int) $id, $request);

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

    public function toggle(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $coach = $db->selectOne(
            "SELECT * FROM sa_coaches WHERE id = ? AND is_archived = 0",
            [(int) $id]
        );

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

        $newStatus = (int) $coach['is_active'] === 1 ? 0 : 1;

        $db->update('sa_coaches', [
            'is_active'  => $newStatus,
            'updated_at' => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        $msg = $newStatus === 1 ? 'تم تفعيل المدرب' : 'تم تعطيل المدرب';
        return $this->redirect('/sa/coaches')->withSuccess($msg);
    }

    private function syncDisciplines(\App\Core\Database $db, int $coachId, Request $request): void
    {
        // Delete existing
        $db->delete('sa_coach_disciplines', '`coach_id` = ?', [$coachId]);

        // Insert new
        $disciplineIds = $request->post('discipline_ids', []);
        $levels = $request->post('levels', []);

        if (!is_array($disciplineIds)) {
            return;
        }

        foreach ($disciplineIds as $index => $disciplineId) {
            $disciplineId = (int) $disciplineId;
            if ($disciplineId <= 0) {
                continue;
            }

            $level = $levels[$index] ?? 'secondary';
            if (!in_array($level, ['primary', 'secondary'])) {
                $level = 'secondary';
            }

            $db->insert('sa_coach_disciplines', [
                'coach_id'             => $coachId,
                'discipline_id'        => $disciplineId,
                'specialization_level' => $level,
                'created_at'           => date('Y-m-d H:i:s'),
            ]);
        }
    }
}
