<?php
declare(strict_types=1);

namespace App\Modules\PlayerAffairs\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\PlayerAffairs\Models\Player;
use App\Modules\PlayerAffairs\Models\AcademyEnrollment;
use App\Modules\PlayerAffairs\Models\PlayerMedicalRecord;
use App\Modules\PlayerAffairs\Services\PlayerRegistrationService;
use App\Modules\PlayerAffairs\Services\PlayerCardService;
use App\Modules\PlayerAffairs\Services\MedicalRecordService;

class PlayerController extends Controller
{
    /**
     * List all players with tabs, status filter, search, and pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'              => trim((string) $request->get('q', '')),
            'player_type'    => trim((string) $request->get('player_type', '')),
            'card_status'    => trim((string) $request->get('card_status', '')),
            'medical_status' => trim((string) $request->get('medical_status', '')),
        ];

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

        return $this->view('PlayerAffairs.Views.index', [
            'players'         => $result['data'],
            'pagination'      => $result['pagination'],
            'filters'         => $filters,
            'playerTypes'     => Player::getPlayerTypes(),
            'cardStatuses'    => Player::getCardStatuses(),
            'medicalStatuses' => Player::getMedicalStatuses(),
        ]);
    }

    /**
     * Show the player registration form.
     */
    public function create(Request $request): Response
    {
        return $this->view('PlayerAffairs.Views.create', [
            'playerTypes'    => Player::getPlayerTypes(),
            'genders'        => Player::getGenders(),
            'relationships'  => Player::getGuardianRelationships(),
        ]);
    }

    /**
     * Validate and register a new player.
     */
    public function store(Request $request): Response
    {
        $playerType = trim((string) $request->post('player_type', ''));
        $fullNameAr = trim((string) $request->post('full_name_ar', ''));
        $fullNameEn = trim((string) $request->post('full_name_en', ''));
        $nationalId = trim((string) $request->post('national_id', ''));
        $passportNumber = trim((string) $request->post('passport_number', ''));
        $dateOfBirth = trim((string) $request->post('date_of_birth', ''));
        $gender = trim((string) $request->post('gender', ''));
        $phone = trim((string) $request->post('phone', ''));
        $email = trim((string) $request->post('email', ''));
        $address = trim((string) $request->post('address', ''));
        $guardianName = trim((string) $request->post('guardian_name', ''));
        $guardianPhone = trim((string) $request->post('guardian_phone', ''));
        $guardianNationalId = trim((string) $request->post('guardian_national_id', ''));
        $guardianRelationship = trim((string) $request->post('guardian_relationship', ''));
        $schoolName = trim((string) $request->post('school_name', ''));
        $schoolGrade = trim((string) $request->post('school_grade', ''));
        $notes = trim((string) $request->post('notes', ''));
        $memberId = $request->post('member_id');

        // Validation
        $errors = [];
        if ($fullNameAr === '' || mb_strlen($fullNameAr) < 2) {
            $errors[] = 'الاسم بالعربي مطلوب (حرفان على الأقل)';
        }
        if (!array_key_exists($playerType, Player::getPlayerTypes())) {
            $errors[] = 'نوع اللاعب غير صالح';
        }
        if ($dateOfBirth === '') {
            $errors[] = 'تاريخ الميلاد مطلوب';
        }
        if ($gender !== '' && !array_key_exists($gender, Player::getGenders())) {
            $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('/players/create');
        }

        $data = [
            'full_name_ar'          => $fullNameAr,
            'full_name_en'          => $fullNameEn ?: null,
            'national_id'           => $nationalId ?: null,
            'passport_number'       => $passportNumber ?: null,
            'date_of_birth'         => $dateOfBirth,
            'gender'                => $gender ?: null,
            'phone'                 => $phone ?: null,
            'email'                 => $email ?: null,
            'address'               => $address ?: null,
            'guardian_name'         => $guardianName ?: null,
            'guardian_phone'        => $guardianPhone ?: null,
            'guardian_national_id'  => $guardianNationalId ?: null,
            'guardian_relationship' => $guardianRelationship ?: null,
            'school_name'           => $schoolName ?: null,
            'school_grade'          => $schoolGrade ?: null,
            'notes'                 => $notes ?: null,
        ];

        try {
            if ($playerType === 'member' && $memberId) {
                $player = PlayerRegistrationService::registerMemberPlayer((int) $memberId, $data);
            } else {
                $player = PlayerRegistrationService::registerNonMemberPlayer($data);
            }
        } catch (\RuntimeException $e) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', [['type' => 'error', 'message' => $e->getMessage()]]);
            $session->flash('_old_input', $request->all());
            return $this->redirect('/players/create');
        }

        return $this->redirect('/players/' . $player->id)->withSuccess('تم تسجيل اللاعب بنجاح');
    }

    /**
     * Show a player's full profile.
     */
    public function show(Request $request, string $id): Response
    {
        $player = Player::find((int) $id);
        if (!$player) {
            return $this->redirect('/players')->withError('اللاعب غير موجود');
        }

        // Derive disciplines from active enrollments (not the redundant player_disciplines table)
        $db = App::getInstance()->db();
        $disciplines = $db->select(
            "SELECT DISTINCT sd.id, sd.name_ar AS discipline_name, sd.icon,
                    a.name_ar AS academy_name, ae.season, ae.status
             FROM academy_enrollments ae
             JOIN academies a ON a.id = ae.academy_id
             JOIN sport_disciplines sd ON sd.id = a.discipline_id
             WHERE ae.player_id = ? AND ae.status IN ('active', 'suspended')
             ORDER BY sd.name_ar",
            [(int) $id]
        );
        $enrollments    = AcademyEnrollment::getForPlayer((int) $id);
        $medicalRecords = PlayerMedicalRecord::getForPlayer((int) $id);

        return $this->view('PlayerAffairs.Views.show', [
            'player'         => $player,
            'disciplines'    => $disciplines,
            'enrollments'    => $enrollments,
            'medicalRecords' => $medicalRecords,
            'cardStatuses'   => Player::getCardStatuses(),
            'medicalStatuses' => Player::getMedicalStatuses(),
            'playerTypes'    => Player::getPlayerTypes(),
            'genders'        => Player::getGenders(),
        ]);
    }

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

        return $this->view('PlayerAffairs.Views.edit', [
            'player'        => $player,
            'playerTypes'   => Player::getPlayerTypes(),
            'genders'       => Player::getGenders(),
            'relationships' => Player::getGuardianRelationships(),
        ]);
    }

    /**
     * Update player information.
     */
    public function update(Request $request, string $id): Response
    {
        $player = Player::find((int) $id);
        if (!$player) {
            return $this->redirect('/players')->withError('اللاعب غير موجود');
        }

        $fullNameAr = trim((string) $request->post('full_name_ar', ''));
        $fullNameEn = trim((string) $request->post('full_name_en', ''));
        $nationalId = trim((string) $request->post('national_id', ''));
        $passportNumber = trim((string) $request->post('passport_number', ''));
        $dateOfBirth = trim((string) $request->post('date_of_birth', ''));
        $gender = trim((string) $request->post('gender', ''));
        $phone = trim((string) $request->post('phone', ''));
        $email = trim((string) $request->post('email', ''));
        $address = trim((string) $request->post('address', ''));
        $guardianName = trim((string) $request->post('guardian_name', ''));
        $guardianPhone = trim((string) $request->post('guardian_phone', ''));
        $guardianNationalId = trim((string) $request->post('guardian_national_id', ''));
        $guardianRelationship = trim((string) $request->post('guardian_relationship', ''));
        $schoolName = trim((string) $request->post('school_name', ''));
        $schoolGrade = trim((string) $request->post('school_grade', ''));
        $notes = trim((string) $request->post('notes', ''));

        // Validation
        $errors = [];
        if ($fullNameAr === '' || mb_strlen($fullNameAr) < 2) {
            $errors[] = 'الاسم بالعربي مطلوب (حرفان على الأقل)';
        }
        if ($dateOfBirth === '') {
            $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('/players/' . $id . '/edit');
        }

        $player->update([
            'full_name_ar'          => $fullNameAr,
            'full_name_en'          => $fullNameEn ?: null,
            'national_id'           => $nationalId ?: null,
            'passport_number'       => $passportNumber ?: null,
            'date_of_birth'         => $dateOfBirth,
            'gender'                => $gender ?: null,
            'phone'                 => $phone ?: null,
            'email'                 => $email ?: null,
            'address'               => $address ?: null,
            'guardian_name'         => $guardianName ?: null,
            'guardian_phone'        => $guardianPhone ?: null,
            'guardian_national_id'  => $guardianNationalId ?: null,
            'guardian_relationship' => $guardianRelationship ?: null,
            'school_name'           => $schoolName ?: null,
            'school_grade'          => $schoolGrade ?: null,
            'notes'                 => $notes ?: null,
        ]);

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

    /**
     * Activate a player's card.
     */
    public function activateCard(Request $request, string $id): Response
    {
        try {
            PlayerCardService::activateCard((int) $id);
        } catch (\RuntimeException $e) {
            return $this->redirect('/players/' . $id)->withError($e->getMessage());
        }

        return $this->redirect('/players/' . $id)->withSuccess('تم تفعيل الكارنيه بنجاح');
    }

    /**
     * Suspend a player's card.
     */
    public function suspendCard(Request $request, string $id): Response
    {
        $reason = trim((string) $request->post('reason', ''));

        try {
            PlayerCardService::suspendCard((int) $id, $reason ?: null);
        } catch (\RuntimeException $e) {
            return $this->redirect('/players/' . $id)->withError($e->getMessage());
        }

        return $this->redirect('/players/' . $id)->withSuccess('تم إيقاف الكارنيه');
    }

    /**
     * Revoke a player's card.
     */
    public function revokeCard(Request $request, string $id): Response
    {
        try {
            PlayerCardService::revokeCard((int) $id);
        } catch (\RuntimeException $e) {
            return $this->redirect('/players/' . $id)->withError($e->getMessage());
        }

        return $this->redirect('/players/' . $id)->withSuccess('تم إلغاء الكارنيه');
    }

    /**
     * Add a medical record for a player.
     */
    public function addMedical(Request $request, string $id): Response
    {
        $data = [
            'record_type'  => trim((string) $request->post('record_type', '')),
            'exam_date'    => trim((string) $request->post('exam_date', '')),
            'expiry_date'  => trim((string) $request->post('expiry_date', '')) ?: null,
            'doctor_name'  => trim((string) $request->post('doctor_name', '')) ?: null,
            'clinic_name'  => trim((string) $request->post('clinic_name', '')) ?: null,
            'result'       => trim((string) $request->post('result', '')),
            'restrictions' => trim((string) $request->post('restrictions', '')) ?: null,
            'document_id'  => $request->post('document_id') ? (int) $request->post('document_id') : null,
            'notes'        => trim((string) $request->post('notes', '')) ?: null,
        ];

        // Validation
        $errors = [];
        if (!array_key_exists($data['record_type'], PlayerMedicalRecord::getRecordTypes())) {
            $errors[] = 'نوع السجل الطبي غير صالح';
        }
        if (empty($data['exam_date'])) {
            $errors[] = 'تاريخ الفحص مطلوب';
        }
        if (!empty($data['result']) && !array_key_exists($data['result'], PlayerMedicalRecord::getResults())) {
            $errors[] = 'نتيجة الفحص غير صالحة';
        }

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

        try {
            MedicalRecordService::addRecord((int) $id, $data);
        } catch (\RuntimeException $e) {
            return $this->redirect('/players/' . $id)->withError($e->getMessage());
        }

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

    /**
     * Enroll a player in an academy.
     */
    public function enroll(Request $request, string $id): Response
    {
        $player = Player::find((int) $id);
        if (!$player) {
            return $this->redirect('/players')->withError('اللاعب غير موجود');
        }

        $academyId  = (int) $request->post('academy_id', 0);
        $levelId    = $request->post('level_id') ? (int) $request->post('level_id') : null;
        $scheduleId = $request->post('schedule_id') ? (int) $request->post('schedule_id') : null;
        $season     = trim((string) $request->post('season', ''));

        if ($academyId <= 0) {
            return $this->redirect('/players/' . $id)->withError('يجب اختيار أكاديمية');
        }

        $employee = App::getInstance()->currentEmployee();

        AcademyEnrollment::create([
            'player_id'      => (int) $id,
            'academy_id'     => $academyId,
            'level_id'       => $levelId,
            'schedule_id'    => $scheduleId,
            'season'         => $season ?: null,
            'enrolled_at'    => date('Y-m-d H:i:s'),
            'enrollment_day' => (int) date('j'),
            'status'         => 'active',
            'created_by'     => $employee ? (int) $employee->id : null,
        ]);

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

    /**
     * Drop (withdraw) a player from an academy enrollment.
     */
    public function dropEnrollment(Request $request, string $id): Response
    {
        $enrollmentId = (int) $request->post('enrollment_id', 0);
        $droppedReason = trim((string) $request->post('dropped_reason', ''));

        if ($enrollmentId <= 0) {
            return $this->redirect('/players/' . $id)->withError('يجب تحديد التسجيل');
        }

        $enrollment = AcademyEnrollment::find($enrollmentId);
        if (!$enrollment || (int) $enrollment->player_id !== (int) $id) {
            return $this->redirect('/players/' . $id)->withError('التسجيل غير موجود');
        }

        $enrollment->update([
            'status'         => 'dropped',
            'dropped_at'     => date('Y-m-d H:i:s'),
            'dropped_reason' => $droppedReason ?: null,
        ]);

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