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

class PlayerController extends Controller
{
    /**
     * List players with search, filters, and pagination.
     */
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();

        $search = trim((string) $request->get('q', ''));
        $playerType = trim((string) $request->get('player_type', ''));
        $medicalStatus = trim((string) $request->get('medical_status', ''));
        $disciplineId = trim((string) $request->get('discipline_id', ''));
        $groupId = trim((string) $request->get('group_id', ''));
        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;

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

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

        if ($playerType !== '') {
            $where[] = 'p.player_type = ?';
            $params[] = $playerType;
        }

        if ($medicalStatus !== '') {
            $where[] = 'p.medical_status = ?';
            $params[] = $medicalStatus;
        }

        if ($groupId !== '') {
            $joins .= ' INNER JOIN sa_group_players gp ON gp.player_id = p.id AND gp.group_id = ? AND gp.status = "active"';
            $params[] = (int) $groupId;
        } elseif ($disciplineId !== '') {
            $joins .= ' INNER JOIN sa_group_players gp ON gp.player_id = p.id AND gp.status = "active"';
            $joins .= ' INNER JOIN sa_groups g ON g.id = gp.group_id AND g.is_archived = 0';
            $joins .= ' INNER JOIN sa_programs pr ON pr.id = g.program_id AND pr.discipline_id = ?';
            $params[] = (int) $disciplineId;
        }

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

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

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

        $sql = "SELECT DISTINCT p.* FROM sa_players p {$joins} WHERE {$whereSql} ORDER BY p.created_at DESC LIMIT {$perPage} OFFSET {$offset}";
        $players = $db->select($sql, $params);

        $disciplines = Discipline::getActive();
        $groups = Group::getActive();

        return $this->view('SportsActivity.Views.players.index', [
            'players'     => $players,
            'pagination'  => $pagination,
            'disciplines' => $disciplines,
            'groups'      => $groups,
            'filters'     => [
                'q'              => $search,
                'player_type'    => $playerType,
                'medical_status' => $medicalStatus,
                'discipline_id'  => $disciplineId,
                'group_id'       => $groupId,
            ],
        ]);
    }

    /**
     * Show the create player form.
     */
    public function create(Request $request): Response
    {
        return $this->view('SportsActivity.Views.players.create', []);
    }

    /**
     * Validate and store a new player.
     */
    public function store(Request $request): Response
    {
        $db = App::getInstance()->db();
        $session = App::getInstance()->session();

        $fullNameAr = trim((string) $request->post('full_name_ar', ''));
        $fullNameEn = trim((string) $request->post('full_name_en', ''));
        $playerType = trim((string) $request->post('player_type', ''));
        $memberId = (int) $request->post('member_id', 0);
        $nationalId = trim((string) $request->post('national_id', ''));
        $dateOfBirth = trim((string) $request->post('date_of_birth', ''));
        $gender = trim((string) $request->post('gender', 'male'));
        $phone = trim((string) $request->post('phone', ''));
        $email = trim((string) $request->post('email', ''));
        $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', ''));
        $notes = trim((string) $request->post('notes', ''));

        // For members: auto-fill from member record (member_id is the DB id set by AJAX lookup)
        if ($playerType === 'member' && $memberId > 0) {
            $member = $db->selectOne(
                "SELECT full_name_ar, national_id, date_of_birth, gender FROM members WHERE id = ? AND is_archived = 0",
                [$memberId]
            );
            if ($member) {
                if ($fullNameAr === '') {
                    $fullNameAr = $member['full_name_ar'] ?? '';
                }
                if ($member['national_id']) {
                    $nationalId = $member['national_id'];
                }
                if ($member['date_of_birth']) {
                    $dateOfBirth = $member['date_of_birth'];
                }
                if ($member['gender']) {
                    $gender = $member['gender'];
                }
            }
        } elseif ($nationalId !== '' && strlen($nationalId) === 14) {
            $parsed = NationalIdParser::parse($nationalId);
            if ($parsed['is_valid']) {
                $dateOfBirth = $parsed['dob'];
                $gender = $parsed['gender'];
            }
        }

        // Validation
        $errors = [];
        if ($fullNameAr === '') {
            $errors[] = 'الاسم بالعربي مطلوب';
        } elseif (mb_strlen($fullNameAr) > 300) {
            $errors[] = 'الاسم بالعربي يجب ألا يتجاوز 300 حرف';
        }
        if ($playerType === '') {
            $errors[] = 'نوع اللاعب مطلوب';
        }
        if ($playerType === 'member' && $memberId <= 0) {
            $errors[] = 'رقم العضوية مطلوب للأعضاء';
        }

        $validTypes = ['member', 'non_member'];
        if ($playerType !== '' && !in_array($playerType, $validTypes, true)) {
            $errors[] = 'نوع اللاعب غير صالح';
        }

        if ($fullNameEn !== '' && mb_strlen($fullNameEn) > 300) {
            $errors[] = 'الاسم بالإنجليزي يجب ألا يتجاوز 300 حرف';
        }
        if ($nationalId !== '' && strlen($nationalId) > 14) {
            $errors[] = 'الرقم القومي يجب ألا يتجاوز 14 رقم';
        }
        if ($phone !== '' && mb_strlen($phone) > 30) {
            $errors[] = 'رقم الهاتف يجب ألا يتجاوز 30 حرف';
        }
        if ($email !== '' && mb_strlen($email) > 200) {
            $errors[] = 'البريد الإلكتروني يجب ألا يتجاوز 200 حرف';
        }
        if ($guardianName !== '' && mb_strlen($guardianName) > 300) {
            $errors[] = 'اسم ولي الأمر يجب ألا يتجاوز 300 حرف';
        }
        if ($guardianPhone !== '' && mb_strlen($guardianPhone) > 30) {
            $errors[] = 'هاتف ولي الأمر يجب ألا يتجاوز 30 حرف';
        }
        if ($guardianNationalId !== '' && strlen($guardianNationalId) > 14) {
            $errors[] = 'الرقم القومي لولي الأمر يجب ألا يتجاوز 14 رقم';
        }
        if ($guardianRelationship !== '' && mb_strlen($guardianRelationship) > 50) {
            $errors[] = 'صلة القرابة يجب ألا تتجاوز 50 حرف';
        }

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

        // Generate registration serial
        $maxSerial = $db->selectOne(
            "SELECT MAX(CAST(SUBSTRING(registration_serial, 5) AS UNSIGNED)) as max_num FROM sa_players WHERE registration_serial LIKE 'SAP-%'"
        );
        $nextNum = ((int) ($maxSerial['max_num'] ?? 0)) + 1;
        $serialNumber = 'SAP-' . str_pad((string) $nextNum, 5, '0', STR_PAD_LEFT);

        $data = [
            'registration_serial'  => $serialNumber,
            'full_name_ar'         => $fullNameAr,
            'full_name_en'         => $fullNameEn ?: null,
            'player_type'          => $playerType,
            'member_id'            => $memberId > 0 ? $memberId : null,
            'national_id'          => $nationalId ?: null,
            'date_of_birth'        => $dateOfBirth ?: null,
            'gender'               => $gender,
            'phone'                => $phone ?: null,
            'email'                => $email ?: null,
            'guardian_name'        => $guardianName ?: null,
            'guardian_phone'       => $guardianPhone ?: null,
            'guardian_national_id' => $guardianNationalId ?: null,
            'guardian_relationship' => $guardianRelationship ?: null,
            'medical_status'       => 'pending',
            'card_status'          => 'inactive',
            'notes'                => $notes ?: null,
            'created_at'           => now(),
            'updated_at'           => now(),
        ];

        $db->insert('sa_players', $data);
        $playerId = (int) $db->selectOne("SELECT LAST_INSERT_ID() as id")['id'];

        return $this->redirect('/sa/players/' . $playerId)->withSuccess('تم إضافة اللاعب بنجاح');
    }

    /**
     * Show player detail with documents list.
     */
    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $player = $db->selectOne("SELECT * FROM sa_players WHERE id = ?", [(int) $id]);
        if (!$player) {
            return $this->redirect('/sa/players')->withError('اللاعب غير موجود');
        }

        $documents = $db->select(
            "SELECT * FROM sa_player_documents WHERE player_id = ? ORDER BY created_at DESC",
            [(int) $id]
        );

        $medicalHistory = $db->select(
            "SELECT * FROM sa_player_documents WHERE player_id = ? AND document_type = 'medical_cert' ORDER BY created_at DESC",
            [(int) $id]
        );

        $employee = App::getInstance()->currentEmployee();
        $canApproveMedical = $employee && method_exists($employee, 'hasPermission') && $employee->hasPermission('sa.medical.approve');

        $unpaidSubs = $db->select(
            "SELECT s.*, g.name_ar as group_name
             FROM sa_subscriptions s
             LEFT JOIN sa_groups g ON g.id = s.group_id
             WHERE s.player_id = ? AND s.payment_status IN ('unpaid', 'overdue', 'partial')
             ORDER BY s.period_start DESC",
            [(int) $id]
        );

        $enrolledGroups = $db->select(
            "SELECT gp.status as enrollment_status, gp.enrolled_at as joined_at,
                    g.id as group_id, g.name_ar as group_name, g.code as group_code,
                    p.name_ar as program_name, c.full_name_ar as coach_name
             FROM sa_group_players gp
             INNER JOIN sa_groups g ON g.id = gp.group_id
             LEFT JOIN sa_programs p ON p.id = g.program_id
             LEFT JOIN sa_coaches c ON c.id = g.coach_id
             WHERE gp.player_id = ? AND gp.status IN ('active', 'pending_payment')
             ORDER BY gp.enrolled_at DESC",
            [(int) $id]
        );

        $recentBookings = $db->select(
            "SELECT b.booking_date, b.start_time, b.end_time, b.booking_type, b.status,
                    fu.name_ar as unit_name, f.name_ar as facility_name
             FROM sa_bookings b
             INNER JOIN sa_facility_units fu ON fu.id = b.facility_unit_id
             INNER JOIN sa_facilities f ON f.id = fu.facility_id
             WHERE b.booker_id = ? AND b.booker_type = 'player'
             ORDER BY b.booking_date DESC, b.start_time DESC
             LIMIT 20",
            [(int) $id]
        );

        $gateHistory = $db->select(
            "SELECT ga.recorded_at as scan_time, ga.granted as access_granted, ga.access_point as gate_name, ga.denial_reason
             FROM sa_gate_access_log ga
             WHERE ga.player_id = ?
             ORDER BY ga.recorded_at DESC
             LIMIT 20",
            [(int) $id]
        );

        $activeCard = $db->selectOne(
            "SELECT id, card_number, status, valid_from, valid_until
             FROM sa_player_cards
             WHERE player_id = ? AND is_archived = 0
             ORDER BY id DESC LIMIT 1",
            [(int) $id]
        );

        $paidRegistration = null;
        if (!$activeCard) {
            $paidRegistration = $db->selectOne(
                "SELECT id FROM sa_registrations
                 WHERE player_id = ? AND payment_status = 'paid' AND card_generated = 0
                 ORDER BY id DESC LIMIT 1",
                [(int) $id]
            );
        }

        return $this->view('SportsActivity.Views.players.show', [
            'player'            => $player,
            'documents'         => $documents,
            'medicalHistory'    => $medicalHistory,
            'canApproveMedical' => $canApproveMedical,
            'unpaidSubs'        => $unpaidSubs,
            'enrolledGroups'    => $enrolledGroups,
            'recentBookings'    => $recentBookings,
            'gateHistory'       => $gateHistory,
            'activeCard'        => $activeCard,
            'paidRegistration'  => $paidRegistration,
        ]);
    }

    /**
     * Show edit form for a player.
     */
    public function edit(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $player = $db->selectOne("SELECT * FROM sa_players WHERE id = ?", [(int) $id]);
        if (!$player) {
            return $this->redirect('/sa/players')->withError('اللاعب غير موجود');
        }

        return $this->view('SportsActivity.Views.players.edit', [
            'player' => $player,
        ]);
    }

    /**
     * Validate and update a player.
     */
    public function update(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $session = App::getInstance()->session();

        $player = $db->selectOne("SELECT * FROM sa_players WHERE id = ?", [(int) $id]);
        if (!$player) {
            return $this->redirect('/sa/players')->withError('اللاعب غير موجود');
        }

        $fullNameAr = trim((string) $request->post('full_name_ar', ''));
        $fullNameEn = trim((string) $request->post('full_name_en', ''));
        $playerType = trim((string) $request->post('player_type', ''));
        $memberId = (int) $request->post('member_id', 0);
        $nationalId = trim((string) $request->post('national_id', ''));
        $dateOfBirth = trim((string) $request->post('date_of_birth', ''));
        $gender = trim((string) $request->post('gender', 'male'));
        $phone = trim((string) $request->post('phone', ''));
        $email = trim((string) $request->post('email', ''));
        $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', ''));
        $notes = trim((string) $request->post('notes', ''));

        // Auto-extract DOB and gender from national ID
        if ($nationalId !== '' && strlen($nationalId) === 14) {
            $parsed = NationalIdParser::parse($nationalId);
            if ($parsed['is_valid']) {
                $dateOfBirth = $parsed['dob'];
                $gender = $parsed['gender'];
            }
        }

        // Validation
        $errors = [];
        if ($fullNameAr === '') {
            $errors[] = 'الاسم بالعربي مطلوب';
        } elseif (mb_strlen($fullNameAr) > 300) {
            $errors[] = 'الاسم بالعربي يجب ألا يتجاوز 300 حرف';
        }
        if ($playerType === '') {
            $errors[] = 'نوع اللاعب مطلوب';
        }
        if ($playerType === 'member' && $memberId <= 0) {
            $errors[] = 'رقم العضوية مطلوب للأعضاء';
        }

        $validTypes = ['member', 'non_member'];
        if ($playerType !== '' && !in_array($playerType, $validTypes, true)) {
            $errors[] = 'نوع اللاعب غير صالح';
        }

        if ($fullNameEn !== '' && mb_strlen($fullNameEn) > 300) {
            $errors[] = 'الاسم بالإنجليزي يجب ألا يتجاوز 300 حرف';
        }
        if ($nationalId !== '' && strlen($nationalId) > 14) {
            $errors[] = 'الرقم القومي يجب ألا يتجاوز 14 رقم';
        }
        if ($phone !== '' && mb_strlen($phone) > 30) {
            $errors[] = 'رقم الهاتف يجب ألا يتجاوز 30 حرف';
        }
        if ($email !== '' && mb_strlen($email) > 200) {
            $errors[] = 'البريد الإلكتروني يجب ألا يتجاوز 200 حرف';
        }
        if ($guardianName !== '' && mb_strlen($guardianName) > 300) {
            $errors[] = 'اسم ولي الأمر يجب ألا يتجاوز 300 حرف';
        }
        if ($guardianPhone !== '' && mb_strlen($guardianPhone) > 30) {
            $errors[] = 'هاتف ولي الأمر يجب ألا يتجاوز 30 حرف';
        }
        if ($guardianNationalId !== '' && strlen($guardianNationalId) > 14) {
            $errors[] = 'الرقم القومي لولي الأمر يجب ألا يتجاوز 14 رقم';
        }
        if ($guardianRelationship !== '' && mb_strlen($guardianRelationship) > 50) {
            $errors[] = 'صلة القرابة يجب ألا تتجاوز 50 حرف';
        }

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

        $data = [
            'full_name_ar'         => $fullNameAr,
            'full_name_en'         => $fullNameEn ?: null,
            'player_type'          => $playerType,
            'member_id'            => $memberId > 0 ? $memberId : null,
            'national_id'          => $nationalId ?: null,
            'date_of_birth'        => $dateOfBirth ?: null,
            'gender'               => $gender,
            'phone'                => $phone ?: null,
            'email'                => $email ?: null,
            'guardian_name'        => $guardianName ?: null,
            'guardian_phone'       => $guardianPhone ?: null,
            'guardian_national_id' => $guardianNationalId ?: null,
            'guardian_relationship' => $guardianRelationship ?: null,
            'notes'                => $notes ?: null,
            'updated_at'           => now(),
        ];

        $db->update('sa_players', $data, 'id = ?', [(int) $id]);

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