<?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;

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

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

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

        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}%";
        }

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

        $total = (int) $db->selectOne(
            "SELECT COUNT(*) as cnt FROM sa_coaches c 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
             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
        );

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

    public function create(Request $request): Response
    {
        $disciplines = Discipline::getActive();
        $employmentTypes = Coach::getEmploymentTypeOptions();
        $paymentModels = Coach::getPaymentModelOptions();

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

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

        $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[] = 'كود المدرب مطلوب';
        }
        if ($fullNameAr === '') {
            $errors[] = 'الاسم بالعربي مطلوب';
        }
        if ($code !== '' && Coach::findByCode($code) !== null) {
            $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');
        }

        $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 ?: null,
            'payment_model'   => $paymentModel ?: null,
            'hourly_rate'     => $hourlyRate !== '' ? (float) $hourlyRate : null,
            'session_rate'    => $sessionRate !== '' ? (float) $sessionRate : null,
            'monthly_rate'    => $monthlyRate !== '' ? (float) $monthlyRate : null,
            'max_groups'      => $maxGroups !== '' ? (int) $maxGroups : null,
            'bio_ar'          => $bioAr ?: null,
            'is_active'       => 1,
            'branch_id'       => App::getInstance()->session()->get('branch_id', 1),
        ]);

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

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

    public function show(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('المدرب غير موجود');
        }

        $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();

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

    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();

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

    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[] = 'كود المدرب مطلوب';
        }
        if ($fullNameAr === '') {
            $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");
        }

        $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 ?: null,
            'payment_model'   => $paymentModel ?: null,
            'hourly_rate'     => $hourlyRate !== '' ? (float) $hourlyRate : null,
            'session_rate'    => $sessionRate !== '' ? (float) $sessionRate : null,
            'monthly_rate'    => $monthlyRate !== '' ? (float) $monthlyRate : null,
            'max_groups'      => $maxGroups !== '' ? (int) $maxGroups : null,
            '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'),
            ]);
        }
    }
}
