<?php
declare(strict_types=1);

namespace App\Modules\TrainingGroups\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\TrainingGroups\Models\TrainingGroup;
use App\Modules\TrainingGroups\Models\GroupMembership;

class TrainingGroupController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'q'          => trim((string) $request->get('q', '')),
            'academy_id' => trim((string) $request->get('academy_id', '')),
            'level_id'   => trim((string) $request->get('level_id', '')),
            'group_type' => trim((string) $request->get('group_type', '')),
            'coach_id'   => trim((string) $request->get('coach_id', '')),
        ];

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

        $db = App::getInstance()->db();
        $academies = $db->select(
            "SELECT id, name_ar FROM academies WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('TrainingGroups.Views.index', [
            'groups'     => $result['data'],
            'pagination' => $result['pagination'],
            'filters'    => $filters,
            'academies'  => $academies,
            'groupTypes' => TrainingGroup::getGroupTypes(),
        ]);
    }

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

        $academies = $db->select(
            "SELECT id, name_ar FROM academies WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );
        $levels = $db->select(
            "SELECT id, academy_id, name_ar FROM academy_levels WHERE is_active = 1 ORDER BY level_order ASC"
        );
        $coaches = $db->select(
            "SELECT id, full_name_ar FROM coaches WHERE is_active = 1 AND is_archived = 0 ORDER BY full_name_ar ASC"
        );
        $facilities = $db->select(
            "SELECT id, name_ar FROM facilities WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('TrainingGroups.Views.create', [
            'academies'    => $academies,
            'levels'       => $levels,
            'coaches'      => $coaches,
            'facilities'   => $facilities,
            'groupTypes'   => TrainingGroup::getGroupTypes(),
            'pricingTiers' => TrainingGroup::getPricingTiers(),
        ]);
    }

    public function store(Request $request): Response
    {
        $data = [
            'name_ar'            => trim((string) $request->post('name_ar', '')),
            'name_en'            => trim((string) $request->post('name_en', '')) ?: null,
            'academy_id'         => (int) $request->post('academy_id', 0),
            'level_id'           => (int) $request->post('level_id', 0),
            'coach_id'           => $request->post('coach_id', '') !== '' ? (int) $request->post('coach_id') : null,
            'facility_id'        => $request->post('facility_id', '') !== '' ? (int) $request->post('facility_id') : null,
            'group_type'         => trim((string) $request->post('group_type', 'group')),
            'min_capacity'       => max(1, (int) $request->post('min_capacity', 1)),
            'max_capacity'       => max(1, (int) $request->post('max_capacity', 20)),
            'age_from'           => $request->post('age_from', '') !== '' ? (int) $request->post('age_from') : null,
            'age_to'             => $request->post('age_to', '') !== '' ? (int) $request->post('age_to') : null,
            'gender_restriction' => trim((string) $request->post('gender_restriction', '')) ?: null,
            'day_of_week'        => $request->post('day_of_week', '') !== '' ? (int) $request->post('day_of_week') : null,
            'start_time'         => trim((string) $request->post('start_time', '')) ?: null,
            'end_time'           => trim((string) $request->post('end_time', '')) ?: null,
            'pricing_tier'       => trim((string) $request->post('pricing_tier', 'standard')),
            'is_active'          => 1,
        ];

        // Auto-generate code
        $code = 'TG_' . strtoupper(substr(str_replace(' ', '', $data['name_ar']), 0, 10)) . '_' . time() % 100000;
        $data['code'] = $code;

        $errors = [];
        if ($data['name_ar'] === '' || mb_strlen($data['name_ar']) < 2) {
            $errors[] = 'اسم المجموعة بالعربي مطلوب (حرفين على الأقل)';
        }
        if ($data['academy_id'] <= 0) {
            $errors[] = 'يجب اختيار أكاديمية';
        }
        if ($data['level_id'] <= 0) {
            $errors[] = 'يجب اختيار مستوى';
        }
        if (!array_key_exists($data['group_type'], TrainingGroup::getGroupTypes())) {
            $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('/training-groups/create');
        }

        $group = TrainingGroup::create($data);

        return $this->redirect('/training-groups/' . $group->id)->withSuccess('تم إنشاء المجموعة التدريبية بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $db = App::getInstance()->db();

        // Get academy & level & coach names
        $academy = $db->selectOne("SELECT name_ar FROM academies WHERE id = ?", [(int) $group->academy_id]);
        $level = $db->selectOne("SELECT name_ar FROM academy_levels WHERE id = ?", [(int) $group->level_id]);
        $coach = $group->coach_id ? $db->selectOne("SELECT full_name_ar FROM coaches WHERE id = ?", [(int) $group->coach_id]) : null;
        $facility = $group->facility_id ? $db->selectOne("SELECT name_ar FROM facilities WHERE id = ?", [(int) $group->facility_id]) : null;

        $members = $group->getMembers();

        // Get available players for add-player form (enrolled in this academy, not in this group)
        $players = $db->select(
            "SELECT ae.id AS enrollment_id, ae.player_id, p.full_name_ar AS player_name
             FROM academy_enrollments ae
             INNER JOIN players p ON p.id = ae.player_id
             WHERE ae.academy_id = ? AND ae.status = 'active'
               AND ae.player_id NOT IN (
                   SELECT gm.player_id FROM group_memberships gm WHERE gm.group_id = ? AND gm.status = 'active'
               )
             ORDER BY p.full_name_ar ASC",
            [(int) $group->academy_id, (int) $id]
        );

        // Get other groups for transfer
        $otherGroups = $db->select(
            "SELECT id, name_ar FROM training_groups WHERE id != ? AND academy_id = ? AND is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC",
            [(int) $id, (int) $group->academy_id]
        );

        return $this->view('TrainingGroups.Views.show', [
            'group'        => $group,
            'academyName'  => $academy['name_ar'] ?? '—',
            'levelName'    => $level['name_ar'] ?? '—',
            'coachName'    => $coach['full_name_ar'] ?? null,
            'facilityName' => $facility['name_ar'] ?? null,
            'members'      => $members,
            'players'      => $players,
            'otherGroups'  => $otherGroups,
            'groupTypes'   => TrainingGroup::getGroupTypes(),
            'pricingTiers' => TrainingGroup::getPricingTiers(),
            'dayNames'     => self::getDayNames(),
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $db = App::getInstance()->db();

        $academies = $db->select(
            "SELECT id, name_ar FROM academies WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );
        $levels = $db->select(
            "SELECT id, academy_id, name_ar FROM academy_levels WHERE is_active = 1 ORDER BY level_order ASC"
        );
        $coaches = $db->select(
            "SELECT id, full_name_ar FROM coaches WHERE is_active = 1 AND is_archived = 0 ORDER BY full_name_ar ASC"
        );
        $facilities = $db->select(
            "SELECT id, name_ar FROM facilities WHERE is_active = 1 AND is_archived = 0 ORDER BY name_ar ASC"
        );

        return $this->view('TrainingGroups.Views.edit', [
            'group'        => $group,
            'academies'    => $academies,
            'levels'       => $levels,
            'coaches'      => $coaches,
            'facilities'   => $facilities,
            'groupTypes'   => TrainingGroup::getGroupTypes(),
            'pricingTiers' => TrainingGroup::getPricingTiers(),
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $data = [
            'name_ar'            => trim((string) $request->post('name_ar', '')),
            'name_en'            => trim((string) $request->post('name_en', '')) ?: null,
            'academy_id'         => (int) $request->post('academy_id', 0),
            'level_id'           => (int) $request->post('level_id', 0),
            'coach_id'           => $request->post('coach_id', '') !== '' ? (int) $request->post('coach_id') : null,
            'facility_id'        => $request->post('facility_id', '') !== '' ? (int) $request->post('facility_id') : null,
            'group_type'         => trim((string) $request->post('group_type', 'group')),
            'min_capacity'       => max(1, (int) $request->post('min_capacity', 1)),
            'max_capacity'       => max(1, (int) $request->post('max_capacity', 20)),
            'age_from'           => $request->post('age_from', '') !== '' ? (int) $request->post('age_from') : null,
            'age_to'             => $request->post('age_to', '') !== '' ? (int) $request->post('age_to') : null,
            'gender_restriction' => trim((string) $request->post('gender_restriction', '')) ?: null,
            'day_of_week'        => $request->post('day_of_week', '') !== '' ? (int) $request->post('day_of_week') : null,
            'start_time'         => trim((string) $request->post('start_time', '')) ?: null,
            'end_time'           => trim((string) $request->post('end_time', '')) ?: null,
            'pricing_tier'       => trim((string) $request->post('pricing_tier', 'standard')),
        ];

        $errors = [];
        if ($data['name_ar'] === '' || mb_strlen($data['name_ar']) < 2) {
            $errors[] = 'اسم المجموعة بالعربي مطلوب (حرفين على الأقل)';
        }
        if ($data['academy_id'] <= 0) {
            $errors[] = 'يجب اختيار أكاديمية';
        }
        if ($data['level_id'] <= 0) {
            $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('/training-groups/' . $id . '/edit');
        }

        // Re-check if group is full based on new max_capacity
        $currentCount = (int) $group->current_count;
        $data['is_full'] = $currentCount >= $data['max_capacity'] ? 1 : 0;

        $group->update($data);

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

    public function toggle(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $newStatus = $group->is_active ? 0 : 1;
        $group->update(['is_active' => $newStatus]);

        $message = $newStatus ? 'تم تفعيل المجموعة' : 'تم إيقاف المجموعة';
        return $this->redirect('/training-groups/' . $id)->withSuccess($message);
    }

    public function addPlayer(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $playerId = (int) $request->post('player_id', 0);
        $enrollmentId = (int) $request->post('enrollment_id', 0);

        if ($playerId <= 0 || $enrollmentId <= 0) {
            return $this->redirect('/training-groups/' . $id)->withError('يجب اختيار لاعب');
        }

        // Check if already in group
        $db = App::getInstance()->db();
        $existing = $db->selectOne(
            "SELECT id FROM group_memberships WHERE group_id = ? AND player_id = ? AND status = 'active'",
            [(int) $id, $playerId]
        );

        if ($existing) {
            return $this->redirect('/training-groups/' . $id)->withError('اللاعب موجود بالفعل في هذه المجموعة');
        }

        // Check capacity
        if ((int) $group->current_count >= (int) $group->max_capacity) {
            return $this->redirect('/training-groups/' . $id)->withError('المجموعة ممتلئة');
        }

        $db->insert('group_memberships', [
            'group_id'      => (int) $id,
            'enrollment_id' => $enrollmentId,
            'player_id'     => $playerId,
            'joined_at'     => date('Y-m-d H:i:s'),
            'status'        => 'active',
        ]);

        // Update count
        $newCount = (int) $group->current_count + 1;
        $isFull = $newCount >= (int) $group->max_capacity ? 1 : 0;
        $group->update(['current_count' => $newCount, 'is_full' => $isFull]);

        return $this->redirect('/training-groups/' . $id)->withSuccess('تم إضافة اللاعب للمجموعة');
    }

    public function removePlayer(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $membershipId = (int) $request->post('membership_id', 0);
        if ($membershipId <= 0) {
            return $this->redirect('/training-groups/' . $id)->withError('بيانات غير صالحة');
        }

        $db = App::getInstance()->db();
        $db->update('group_memberships', [
            'status' => 'removed',
            'left_at' => date('Y-m-d H:i:s'),
        ], 'id = ? AND group_id = ?', [$membershipId, (int) $id]);

        // Update count
        $newCount = max(0, (int) $group->current_count - 1);
        $group->update(['current_count' => $newCount, 'is_full' => 0]);

        // Process waiting list for open spot
        \App\Modules\TrainingGroups\Services\WaitingListService::processOpenSpot((int) $id);

        return $this->redirect('/training-groups/' . $id)->withSuccess('تم إزالة اللاعب من المجموعة');
    }

    public function transferPlayer(Request $request, string $id): Response
    {
        $group = TrainingGroup::find((int) $id);
        if (!$group) {
            return $this->redirect('/training-groups')->withError('المجموعة غير موجودة');
        }

        $membershipId = (int) $request->post('membership_id', 0);
        $targetGroupId = (int) $request->post('target_group_id', 0);
        $reason = trim((string) $request->post('transfer_reason', ''));

        if ($membershipId <= 0 || $targetGroupId <= 0) {
            return $this->redirect('/training-groups/' . $id)->withError('بيانات غير صالحة');
        }

        $targetGroup = TrainingGroup::find($targetGroupId);
        if (!$targetGroup) {
            return $this->redirect('/training-groups/' . $id)->withError('المجموعة المستهدفة غير موجودة');
        }

        if ((int) $targetGroup->current_count >= (int) $targetGroup->max_capacity) {
            return $this->redirect('/training-groups/' . $id)->withError('المجموعة المستهدفة ممتلئة');
        }

        $db = App::getInstance()->db();

        // Get the membership
        $membership = $db->selectOne(
            "SELECT * FROM group_memberships WHERE id = ? AND group_id = ? AND status = 'active'",
            [$membershipId, (int) $id]
        );

        if (!$membership) {
            return $this->redirect('/training-groups/' . $id)->withError('العضوية غير موجودة');
        }

        // Mark old membership as transferred
        $db->update('group_memberships', [
            'status'                  => 'transferred',
            'left_at'                 => date('Y-m-d H:i:s'),
            'transferred_to_group_id' => $targetGroupId,
            'transfer_reason'         => $reason ?: null,
        ], 'id = ?', [$membershipId]);

        // Create new membership in target group
        $db->insert('group_memberships', [
            'group_id'      => $targetGroupId,
            'enrollment_id' => (int) $membership['enrollment_id'],
            'player_id'     => (int) $membership['player_id'],
            'joined_at'     => date('Y-m-d H:i:s'),
            'status'        => 'active',
        ]);

        // Update counts
        $newSourceCount = max(0, (int) $group->current_count - 1);
        $group->update(['current_count' => $newSourceCount, 'is_full' => 0]);

        $newTargetCount = (int) $targetGroup->current_count + 1;
        $isTargetFull = $newTargetCount >= (int) $targetGroup->max_capacity ? 1 : 0;
        $targetGroup->update(['current_count' => $newTargetCount, 'is_full' => $isTargetFull]);

        // Process waiting list for open spot in source group
        \App\Modules\TrainingGroups\Services\WaitingListService::processOpenSpot((int) $id);

        return $this->redirect('/training-groups/' . $id)->withSuccess('تم نقل اللاعب بنجاح');
    }

    private static function getDayNames(): array
    {
        return [
            0 => 'الأحد',
            1 => 'الإثنين',
            2 => 'الثلاثاء',
            3 => 'الأربعاء',
            4 => 'الخميس',
            5 => 'الجمعة',
            6 => 'السبت',
        ];
    }
}
