<?php

class ClassController extends Controller
{
    public function index(Request $request): void
    {
        $db = $this->db();
        $sports = $db->fetchAll("SELECT id, name_en FROM sports WHERE is_active = 1 ORDER BY name_en");
        $statuses = ['planned','enrollment_open','active','full','completed','cancelled'];

        $this->view('classes/index', [
            'title' => lang('sports.classes'),
            'breadcrumbs' => [['label' => lang('sports.title'), 'url' => '/sports'], ['label' => lang('sports.classes')]],
            'sports' => $sports,
            'statuses' => $statuses,
        ]);
    }

    public function create(Request $request): void
    {
        $db = $this->db();
        $sports = $db->fetchAll("SELECT id, name_en FROM sports WHERE is_active = 1 ORDER BY name_en");
        $coaches = $db->fetchAll("SELECT id, CONCAT(first_name_en,' ',last_name_en) as name FROM sport_coaches WHERE status = 'active' ORDER BY first_name_en");
        $facilities = $db->fetchAll("SELECT id, name_en FROM facilities WHERE is_active = 1 ORDER BY name_en");
        $seasons = $db->fetchAll("SELECT ss.id, CONCAT(sp.name_en, ' - ', ss.name_en) as name FROM sport_seasons ss LEFT JOIN sports sp ON ss.sport_id = sp.id WHERE ss.status IN ('upcoming','registration','active') ORDER BY ss.start_date DESC");

        $this->view('classes/create', [
            'title' => lang('sports.create_class'),
            'breadcrumbs' => [['label' => lang('sports.title'), 'url' => '/sports'], ['label' => lang('sports.classes'), 'url' => '/sports/classes'], ['label' => lang('common.create')]],
            'sports' => $sports, 'coaches' => $coaches, 'facilities' => $facilities, 'seasons' => $seasons,
        ]);
    }

    public function store(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }
        $validator = new Validator($request->all(), [
            'class_code' => 'required|string|max:20|unique:sport_classes,class_code',
            'sport_id' => 'required|integer|exists:sports,id',
            'name_en' => 'required|string|max:300',
            'name_ar' => 'nullable|string|max:300',
            'coach_id' => 'nullable|integer',
            'facility_id' => 'nullable|integer',
            'class_type' => 'required|in:beginner,intermediate,advanced,all_levels,kids,youth,adult,senior',
            'max_participants' => 'required|integer|min:1',
            'min_participants' => 'nullable|integer',
            'fee_per_session' => 'nullable|decimal',
            'fee_per_month' => 'nullable|decimal',
            'fee_per_term' => 'nullable|decimal',
            'session_duration_minutes' => 'nullable|integer',
            'gender_restriction' => 'required|in:male,female,both',
            'min_age' => 'nullable|integer',
            'max_age' => 'nullable|integer',
            'season_id' => 'nullable|integer',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
            'status' => 'required|in:planned,enrollment_open,active,full,completed,cancelled',
        ]);
        if ($validator->fails()) { $this->json(['success' => false, 'errors' => $validator->errors()], 422); return; }
        $data = $validator->validated();
        $data['is_active'] = 1;
        $data['min_participants'] = $data['min_participants'] ?? 1;
        $data['session_duration_minutes'] = $data['session_duration_minutes'] ?? 60;
        $data['fee_per_session'] = $data['fee_per_session'] ?? 0;
        $data['fee_per_month'] = $data['fee_per_month'] ?? 0;
        $data['fee_per_term'] = $data['fee_per_term'] ?? 0;

        $id = $this->db()->insert('sport_classes', $data);

        // Save schedules
        $days = $request->post('schedule_day', []);
        $startTimes = $request->post('schedule_start', []);
        $endTimes = $request->post('schedule_end', []);
        if (is_array($days)) {
            for ($i = 0; $i < count($days); $i++) {
                if (!empty($days[$i]) && !empty($startTimes[$i]) && !empty($endTimes[$i])) {
                    $this->db()->insert('sport_class_schedules', [
                        'class_id' => $id,
                        'day_of_week' => (int)$days[$i],
                        'start_time' => $startTimes[$i],
                        'end_time' => $endTimes[$i],
                        'facility_id' => $data['facility_id'],
                        'coach_id' => $data['coach_id'],
                        'is_active' => 1,
                    ]);
                }
            }
        }

        $this->audit('create', 'sport_class', $id, "Created class: {$data['name_en']}");
        $this->json(['success' => true, 'message' => 'Class created', 'redirect' => '/sports/classes/' . $id]);
    }

    public function show(Request $request): void
    {
        $id = (int) $request->routeParam('id');
        $db = $this->db();
        $class = $db->fetchOne(
            "SELECT cl.*, sp.name_en as sport_name, CONCAT(co.first_name_en,' ',co.last_name_en) as coach_name, f.name_en as facility_name
             FROM sport_classes cl LEFT JOIN sports sp ON cl.sport_id = sp.id LEFT JOIN sport_coaches co ON cl.coach_id = co.id LEFT JOIN facilities f ON cl.facility_id = f.id
             WHERE cl.id = ?", [$id]);
        if (!$class) { $this->abort(404); return; }

        $schedules = $db->fetchAll("SELECT * FROM sport_class_schedules WHERE class_id = ? AND is_active = 1 ORDER BY day_of_week", [$id]);
        $enrollments = $db->fetchAll(
            "SELECT e.*, m.full_name_en as member_name, m.membership_number, d.full_name_en as dependent_name
             FROM sport_class_enrollments e LEFT JOIN members m ON e.member_id = m.id LEFT JOIN member_dependents d ON e.dependent_id = d.id
             WHERE e.class_id = ? ORDER BY e.enrollment_date DESC", [$id]);
        $waitlist = $db->fetchAll(
            "SELECT w.*, m.full_name_en as member_name, m.membership_number
             FROM sport_class_waitlist w LEFT JOIN members m ON w.member_id = m.id
             WHERE w.class_id = ? AND w.status = 'waiting' ORDER BY w.queue_position", [$id]);

        $enrolledCount = $db->fetchColumn("SELECT COUNT(*) FROM sport_class_enrollments WHERE class_id = ? AND status IN ('enrolled','active')", [$id]);

        $this->view('classes/show', [
            'title' => $class['name_en'],
            'breadcrumbs' => [['label' => lang('sports.title'), 'url' => '/sports'], ['label' => lang('sports.classes'), 'url' => '/sports/classes'], ['label' => $class['name_en']]],
            'class' => $class, 'schedules' => $schedules, 'enrollments' => $enrollments, 'waitlist' => $waitlist, 'enrolledCount' => $enrolledCount,
        ]);
    }

    public function edit(Request $request): void
    {
        $id = (int) $request->routeParam('id');
        $db = $this->db();
        $class = $db->fetchOne("SELECT * FROM sport_classes WHERE id = ?", [$id]);
        if (!$class) { $this->abort(404); return; }

        $sports = $db->fetchAll("SELECT id, name_en FROM sports WHERE is_active = 1 ORDER BY name_en");
        $coaches = $db->fetchAll("SELECT id, CONCAT(first_name_en,' ',last_name_en) as name FROM sport_coaches WHERE status = 'active' ORDER BY first_name_en");
        $facilities = $db->fetchAll("SELECT id, name_en FROM facilities WHERE is_active = 1 ORDER BY name_en");
        $schedules = $db->fetchAll("SELECT * FROM sport_class_schedules WHERE class_id = ? AND is_active = 1 ORDER BY day_of_week", [$id]);

        $this->view('classes/edit', [
            'title' => 'Edit: ' . $class['name_en'],
            'breadcrumbs' => [['label' => lang('sports.title'), 'url' => '/sports'], ['label' => lang('sports.classes'), 'url' => '/sports/classes'], ['label' => lang('common.edit')]],
            'class' => $class, 'sports' => $sports, 'coaches' => $coaches, 'facilities' => $facilities, 'schedules' => $schedules,
        ]);
    }

    public function update(Request $request): void
    {
        $id = (int) $request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }
        $validator = new Validator($request->all(), [
            'name_en' => 'required|string|max:300',
            'name_ar' => 'nullable|string|max:300',
            'coach_id' => 'nullable|integer',
            'facility_id' => 'nullable|integer',
            'class_type' => 'required|in:beginner,intermediate,advanced,all_levels,kids,youth,adult,senior',
            'max_participants' => 'required|integer|min:1',
            'fee_per_month' => 'nullable|decimal',
            'status' => 'required|in:planned,enrollment_open,active,full,completed,cancelled',
        ]);
        if ($validator->fails()) { $this->json(['success' => false, 'errors' => $validator->errors()], 422); return; }
        $data = $validator->validated();
        $data['fee_per_month'] = $data['fee_per_month'] ?? 0;
        $this->db()->update('sport_classes', $data, 'id = ?', [$id]);
        $this->audit('update', 'sport_class', $id, "Updated class: {$data['name_en']}");
        $this->json(['success' => true, 'message' => 'Class updated', 'redirect' => '/sports/classes/' . $id]);
    }

    public function enroll(Request $request): void
    {
        $classId = (int) $request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }

        $memberId = (int) $request->post('member_id');
        $dependentId = $request->post('dependent_id') ? (int) $request->post('dependent_id') : null;
        $db = $this->db();

        $class = $db->fetchOne("SELECT * FROM sport_classes WHERE id = ?", [$classId]);
        if (!$class) { $this->json(['success' => false, 'message' => 'Class not found'], 404); return; }

        $enrolledCount = $db->fetchColumn("SELECT COUNT(*) FROM sport_class_enrollments WHERE class_id = ? AND status IN ('enrolled','active')", [$classId]);
        if ($enrolledCount >= $class['max_participants']) {
            $maxPos = $db->fetchColumn("SELECT COALESCE(MAX(queue_position),0) FROM sport_class_waitlist WHERE class_id = ?", [$classId]);
            $db->insert('sport_class_waitlist', [
                'class_id' => $classId, 'member_id' => $memberId, 'dependent_id' => $dependentId,
                'queue_position' => $maxPos + 1, 'status' => 'waiting',
            ]);
            $this->audit('create', 'sport_class_waitlist', null, "Added to waitlist for class #{$classId}");
            $this->json(['success' => true, 'message' => 'Class full — added to waitlist']);
            return;
        }

        $feeAmount = $class['fee_per_month'] ?: 0;
        $db->insert('sport_class_enrollments', [
            'class_id' => $classId, 'member_id' => $memberId, 'dependent_id' => $dependentId,
            'enrollment_date' => date('Y-m-d'), 'start_date' => date('Y-m-d'),
            'status' => 'enrolled', 'fee_type' => 'monthly', 'fee_amount' => $feeAmount,
            'created_by' => auth_id(),
        ]);
        $this->audit('create', 'sport_class_enrollment', null, "Enrolled member #{$memberId} in class #{$classId}");
        $this->json(['success' => true, 'message' => 'Member enrolled successfully', 'redirect' => '/sports/classes/' . $classId]);
    }

    public function withdraw(Request $request): void
    {
        $classId = (int) $request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }
        $enrollmentId = (int) $request->post('enrollment_id');
        $this->db()->update('sport_class_enrollments', [
            'status' => 'withdrawn', 'withdrawn_date' => date('Y-m-d'),
            'withdrawal_reason' => $request->post('reason', 'Withdrawn by staff'),
        ], 'id = ? AND class_id = ?', [$enrollmentId, $classId]);
        $this->audit('update', 'sport_class_enrollment', $enrollmentId, "Withdrawn from class #{$classId}");
        $this->json(['success' => true, 'message' => 'Member withdrawn', 'redirect' => '/sports/classes/' . $classId]);
    }

    public function attendance(Request $request): void
    {
        $classId = (int) $request->routeParam('id');
        $db = $this->db();
        $class = $db->fetchOne("SELECT cl.*, sp.name_en as sport_name FROM sport_classes cl LEFT JOIN sports sp ON cl.sport_id = sp.id WHERE cl.id = ?", [$classId]);
        if (!$class) { $this->abort(404); return; }

        $sessionDate = $request->get('date', date('Y-m-d'));
        $enrollments = $db->fetchAll(
            "SELECT e.*, m.full_name_en as member_name, m.membership_number, d.full_name_en as dependent_name
             FROM sport_class_enrollments e LEFT JOIN members m ON e.member_id = m.id LEFT JOIN member_dependents d ON e.dependent_id = d.id
             WHERE e.class_id = ? AND e.status IN ('enrolled','active') ORDER BY m.full_name_en", [$classId]);

        $existing = $db->fetchAll("SELECT * FROM sport_class_attendance WHERE class_id = ? AND session_date = ?", [$classId, $sessionDate]);
        $attendanceMap = [];
        foreach ($existing as $att) { $attendanceMap[$att['enrollment_id']] = $att; }

        $this->view('classes/attendance', [
            'title' => 'Attendance: ' . $class['name_en'],
            'breadcrumbs' => [['label' => lang('sports.title'), 'url' => '/sports'], ['label' => lang('sports.classes'), 'url' => '/sports/classes'], ['label' => $class['name_en'], 'url' => '/sports/classes/' . $classId], ['label' => 'Attendance']],
            'class' => $class, 'enrollments' => $enrollments, 'sessionDate' => $sessionDate, 'attendanceMap' => $attendanceMap,
        ]);
    }

    public function saveAttendance(Request $request): void
    {
        $classId = (int) $request->routeParam('id');
        if (!CSRF::validate($request->csrfToken())) { $this->json(['success' => false, 'message' => 'Invalid token'], 403); return; }

        $sessionDate = $request->post('session_date', date('Y-m-d'));
        $sessionStart = $request->post('session_start', '00:00');
        $statuses = $request->post('attendance', []);
        $db = $this->db();

        $db->delete('sport_class_attendance', 'class_id = ? AND session_date = ?', [$classId, $sessionDate]);

        foreach ($statuses as $enrollmentId => $status) {
            if (!in_array($status, ['present','absent','late','excused','cancelled'])) continue;
            $db->insert('sport_class_attendance', [
                'class_id' => $classId, 'enrollment_id' => (int) $enrollmentId,
                'session_date' => $sessionDate, 'session_start' => $sessionStart,
                'status' => $status, 'recorded_by' => auth_id(),
            ]);
        }

        $this->audit('create', 'sport_class_attendance', null, "Recorded attendance for class #{$classId} on {$sessionDate}");
        $this->json(['success' => true, 'message' => 'Attendance saved', 'redirect' => '/sports/classes/' . $classId . '/attendance?date=' . $sessionDate]);
    }
}