<?php

namespace App\Controllers;

class AdminController {
    private $pdo;
    private $config;
    
    public function __construct($pdo, $config) {
        $this->pdo = $pdo;
        $this->config = $config;
    }
    
    private function requireAdmin() {
        \App\Middleware\AuthMiddleware::requireAuth();
        \App\Middleware\AuthMiddleware::requireRole(['super_admin', 'academic_admin', 'finance_officer', 'assessor', 'auditor', 'support_officer']);
    }
    
    private function getAdminStats() {
        $stats = [];
        $stats['total_students'] = $this->pdo->query("SELECT COUNT(*) FROM students")->fetchColumn();
        $stats['new_applications'] = $this->pdo->query("SELECT COUNT(*) FROM applications WHERE status = 'pending'")->fetchColumn();
        $stats['active_students'] = $this->pdo->query("SELECT COUNT(*) FROM students WHERE enrollment_status = 'active'")->fetchColumn();
        $stats['pending_payments'] = $this->pdo->query("SELECT COUNT(*) FROM payments WHERE status = 'submitted'")->fetchColumn();
        $stats['approved_payments'] = $this->pdo->query("SELECT COUNT(*) FROM payments WHERE status = 'approved'")->fetchColumn();
        $stats['total_courses'] = $this->pdo->query("SELECT COUNT(*) FROM courses WHERE is_published = 1")->fetchColumn();
        $stats['total_enrollments'] = $this->pdo->query("SELECT COUNT(*) FROM enrollments WHERE status = 'active'")->fetchColumn();
        $stats['certificates_issued'] = $this->pdo->query("SELECT COUNT(*) FROM certificates WHERE status = 'issued'")->fetchColumn();
        $stats['total_tests'] = $this->pdo->query("SELECT COUNT(*) FROM test_attempts WHERE status = 'completed'")->fetchColumn();
        $stats['pass_rate'] = 0;
        $totalCompleted = $stats['total_tests'];
        if ($totalCompleted > 0) {
            $passed = $this->pdo->query("SELECT COUNT(*) FROM test_attempts WHERE status = 'completed' AND passed = 1")->fetchColumn();
            $stats['pass_rate'] = round(($passed / $totalCompleted) * 100, 1);
        }
        $stats['total_revenue'] = $this->pdo->query("SELECT COALESCE(SUM(amount), 0) FROM payments WHERE status = 'approved'")->fetchColumn();
        return $stats;
    }
    
    public function dashboard() {
        $this->requireAdmin();
        $user = current_user();
        $stats = $this->getAdminStats();
        
        $recentApplications = $this->pdo->query("SELECT a.*, a.id as app_id FROM applications a ORDER BY a.created_at DESC LIMIT 10")->fetchAll();
        $recentPayments = $this->pdo->query("SELECT p.*, s.student_number, u.first_name, u.last_name FROM payments p JOIN students s ON p.student_id = s.id JOIN users u ON s.user_id = u.id ORDER BY p.created_at DESC LIMIT 10")->fetchAll();
        $recentAuditLogs = $this->pdo->query("SELECT al.*, u.first_name, u.last_name FROM audit_logs al LEFT JOIN users u ON al.user_id = u.id ORDER BY al.created_at DESC LIMIT 10")->fetchAll();
        $recentStudents = $this->pdo->query("SELECT s.*, u.first_name, u.last_name, u.email FROM students s JOIN users u ON s.user_id = u.id ORDER BY s.created_at DESC LIMIT 10")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/dashboard.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== APPLICATIONS ==========
    public function applications() {
        $this->requireAdmin();
        $user = current_user();
        $status = $_GET['status'] ?? '';
        $search = $_GET['search'] ?? '';
        $page = max(1, (int)($_GET['page'] ?? 1));
        $perPage = 20;
        
        $where = "WHERE 1=1";
        $params = [];
        if ($status) { $where .= " AND a.status = ?"; $params[] = $status; }
        if ($search) { $where .= " AND (a.first_name LIKE ? OR a.last_name LIKE ? OR a.email LIKE ? OR a.phone LIKE ?)"; $s = "%$search%"; $params = array_merge($params, [$s, $s, $s, $s]); }
        
        $total = $this->pdo->prepare("SELECT COUNT(*) FROM applications a $where");
        $total->execute($params);
        $pagination = paginate($total->fetchColumn(), $perPage, $page);
        
        $stmt = $this->pdo->prepare("SELECT a.* FROM applications a $where ORDER BY a.created_at DESC LIMIT $perPage OFFSET {$pagination['offset']}");
        $stmt->execute($params);
        $applications = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/applications.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function applicationView($id) {
        $this->requireAdmin();
        $user = current_user();
        
        $stmt = $this->pdo->prepare("SELECT a.*, p.name as package_name FROM applications a LEFT JOIN packages p ON a.interested_package_id = p.id WHERE a.id = ?");
        $stmt->execute([$id]);
        $application = $stmt->fetch();
        if (!$application) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $action = $_POST['action'] ?? '';
            $reviewNotes = trim($_POST['review_notes'] ?? '');
            
            if ($action === 'accept') {
                $this->pdo->beginTransaction();
                try {
                    $passwordHash = $application['password_hash'];
                    $stmt = $this->pdo->prepare("INSERT INTO users (role_id, first_name, last_name, email, phone, whatsapp, password_hash, is_active, email_verified_at) VALUES (6, ?, ?, ?, ?, ?, ?, 1, NOW())");
                    $stmt->execute([$application['first_name'], $application['last_name'], $application['email'], $application['phone'], $application['whatsapp'], $passwordHash]);
                    $userId = $this->pdo->lastInsertId();
                    
                    $studentNumber = generate_student_number($this->pdo);
                    $stmt = $this->pdo->prepare("INSERT INTO students (user_id, student_number, id_passport, province, town, highest_education, application_status, payment_status) VALUES (?, ?, ?, ?, ?, ?, 'accepted', 'pending')");
                    $stmt->execute([$userId, $studentNumber, $application['id_passport'], $application['province'], $application['town'], $application['highest_education']]);
                    
                    $stmt = $this->pdo->prepare("UPDATE applications SET status = 'accepted', student_id = (SELECT id FROM students WHERE user_id = ?), reviewed_by = ?, review_notes = ?, reviewed_at = NOW() WHERE id = ?");
                    $stmt->execute([$userId, $user['id'], $reviewNotes, $id]);
                    
                    $this->pdo->commit();
                    
                    $loginUrl = base_url('login');
                    $body = '<h2>Application Accepted</h2><p>Dear ' . e($application['first_name']) . ' ' . e($application['last_name']) . ',</p><p>Your application has been accepted! Your student number is: <strong>' . $studentNumber . '</strong></p><p>Login URL: <a href="' . $loginUrl . '">' . $loginUrl . '</a></p><p>Email: ' . e($application['email']) . '</p><hr><h3>Payment Instructions</h3><p>Use your student number <strong>' . $studentNumber . '</strong> as payment reference.</p><h3>Banking Details</h3><p><strong>Standard Bank</strong><br>Account Name: CIX CONNECT<br>Account Number: 10200349927<br>Branch Code: 051001</p><p><strong>Capitec Business</strong><br>Account Name: CIX CONNECT<br>Account Number: 1051396964<br>Branch Code: 450105</p><p><strong>ABSA</strong><br>Account Name: CIX CONNECT<br>Account Number: 4123963036<br>Branch Code: 632005</p><p>Email proof of payment to: academic@cixconnect.co.za<br>WhatsApp proof: 083 759 8075</p>';
                    send_email($application['email'], 'CIX Orbit Academy - Application Accepted - Student Number: ' . $studentNumber, $body);
                    
                    log_audit($user['id'], 'application_accept', 'application', $id);
                    flash('success', 'Application accepted. Student account created.');
                } catch (\Exception $e) {
                    $this->pdo->rollBack();
                    flash('error', 'Error accepting application: ' . $e->getMessage());
                }
            } elseif ($action === 'reject') {
                $this->pdo->prepare("UPDATE applications SET status = 'rejected', reviewed_by = ?, review_notes = ?, reviewed_at = NOW() WHERE id = ?")->execute([$user['id'], $reviewNotes, $id]);
                log_audit($user['id'], 'application_reject', 'application', $id);
                flash('success', 'Application rejected.');
            }
            redirect(base_url('admin/applications'));
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/application_view.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== STUDENTS ==========
    public function students() {
        $this->requireAdmin();
        $user = current_user();
        $search = $_GET['search'] ?? '';
        $page = max(1, (int)($_GET['page'] ?? 1));
        $perPage = 20;
        
        $where = "WHERE 1=1";
        $params = [];
        if ($search) { $where .= " AND (s.student_number LIKE ? OR u.first_name LIKE ? OR u.last_name LIKE ? OR u.email LIKE ? OR u.phone LIKE ?)"; $s = "%$search%"; $params = array_merge($params, [$s, $s, $s, $s, $s]); }
        
        $total = $this->pdo->prepare("SELECT COUNT(*) FROM students s JOIN users u ON s.user_id = u.id $where");
        $total->execute($params);
        $pagination = paginate($total->fetchColumn(), $perPage, $page);
        
        $stmt = $this->pdo->prepare("SELECT s.*, u.first_name, u.last_name, u.email, u.phone, u.is_active, u.last_login_at, p.name as package_name FROM students s JOIN users u ON s.user_id = u.id LEFT JOIN packages p ON s.current_package_id = p.id $where ORDER BY s.created_at DESC LIMIT $perPage OFFSET {$pagination['offset']}");
        $stmt->execute($params);
        $students = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/students.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function studentView($id) {
        $this->requireAdmin();
        $user = current_user();
        
        $stmt = $this->pdo->prepare("SELECT s.*, u.first_name, u.last_name, u.email, u.phone, u.whatsapp, u.is_active, u.bio, p.name as package_name FROM students s JOIN users u ON s.user_id = u.id LEFT JOIN packages p ON s.current_package_id = p.id WHERE s.id = ?");
        $stmt->execute([$id]);
        $student = $stmt->fetch();
        if (!$student) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        $stmt = $this->pdo->prepare("SELECT e.*, c.title as course_title FROM enrollments e JOIN courses c ON e.course_id = c.id WHERE e.student_id = ? ORDER BY e.enrolled_at DESC");
        $stmt->execute([$id]);
        $enrollments = $stmt->fetchAll();
        
        $stmt = $this->pdo->prepare("SELECT * FROM payments WHERE student_id = ? ORDER BY created_at DESC");
        $stmt->execute([$id]);
        $payments = $stmt->fetchAll();
        
        $stmt = $this->pdo->prepare("SELECT * FROM certificates WHERE student_id = ? ORDER BY created_at DESC");
        $stmt->execute([$id]);
        $certificates = $stmt->fetchAll();
        
        $stmt = $this->pdo->prepare("SELECT ta.*, t.title as test_title FROM test_attempts ta JOIN tests t ON ta.test_id = t.id WHERE ta.student_id = ? ORDER BY ta.created_at DESC LIMIT 10");
        $stmt->execute([$id]);
        $testAttempts = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/student_view.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function studentUpdate($id) {
        $this->requireAdmin();
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $active = isset($_POST['is_active']) ? 1 : 0;
            $status = $_POST['enrollment_status'] ?? 'not_enrolled';
            $this->pdo->prepare("UPDATE students SET enrollment_status = ? WHERE id = ?")->execute([$status, $id]);
            $this->pdo->prepare("UPDATE users SET is_active = ? WHERE id = (SELECT user_id FROM students WHERE id = ?)")->execute([$active, $id]);
            log_audit(current_user()['id'], 'student_update', 'student', $id);
            flash('success', 'Student updated successfully.');
        }
        redirect(base_url('admin/student/' . $id));
    }
    
    // ========== TEACHERS ==========
    public function teachers() {
        $this->requireAdmin();
        $user = current_user();
        $search = $_GET['search'] ?? '';
        
        $where = "WHERE r.slug = 'teacher'";
        $params = [];
        if ($search) { $where .= " AND (u.first_name LIKE ? OR u.last_name LIKE ? OR u.email LIKE ?)"; $s = "%$search%"; $params = array_merge($params, [$s, $s, $s]); }
        
        $stmt = $this->pdo->prepare("SELECT u.*, t.specialization, t.qualifications, t.experience_years, t.is_active as teacher_active FROM users u JOIN roles r ON u.role_id = r.id LEFT JOIN teachers t ON t.user_id = u.id $where ORDER BY u.created_at DESC");
        $stmt->execute($params);
        $teachers = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/teachers.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function teacherCreate() {
        $this->requireAdmin();
        $error = '';
        $success = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $firstName = trim($_POST['first_name'] ?? '');
            $lastName = trim($_POST['last_name'] ?? '');
            $email = trim($_POST['email'] ?? '');
            $phone = trim($_POST['phone'] ?? '');
            $password = $_POST['password'] ?? '';
            $specialization = trim($_POST['specialization'] ?? '');
            $qualifications = trim($_POST['qualifications'] ?? '');
            $experience = (int)($_POST['experience_years'] ?? 0);
            
            if (empty($firstName) || empty($lastName) || empty($email) || empty($password)) {
                $error = 'Please fill all required fields.';
            } else {
                $stmt = $this->pdo->prepare("SELECT id FROM users WHERE email = ?");
                $stmt->execute([$email]);
                if ($stmt->fetch()) {
                    $error = 'A user with this email already exists.';
                } else {
                    $hash = password_hash($password, PASSWORD_DEFAULT);
                    $this->pdo->prepare("INSERT INTO users (role_id, first_name, last_name, email, phone, password_hash, is_active, email_verified_at) VALUES (4, ?, ?, ?, ?, ?, 1, NOW())")->execute([$firstName, $lastName, $email, $phone, $hash]);
                    $userId = $this->pdo->lastInsertId();
                    $empId = 'TCH-' . str_pad($userId, 3, '0', STR_PAD_LEFT);
                    $this->pdo->prepare("INSERT INTO teachers (user_id, employee_id, specialization, qualifications, experience_years, is_active) VALUES (?, ?, ?, ?, ?, 1)")->execute([$userId, $empId, $specialization, $qualifications, $experience]);
                    log_audit(current_user()['id'], 'teacher_create', 'teacher', $userId);
                    flash('success', 'Teacher created successfully.');
                    redirect(base_url('admin/teachers'));
                }
            }
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/teacher_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== COURSES ==========
    public function courses() {
        $this->requireAdmin();
        $user = current_user();
        
        $stmt = $this->pdo->query("SELECT c.*, cc.name as category_name, cl.name as level_name, u.first_name, u.last_name FROM courses c LEFT JOIN course_categories cc ON c.category_id = cc.id LEFT JOIN course_levels cl ON c.level_id = cl.id LEFT JOIN users u ON c.created_by = u.id ORDER BY c.created_at DESC");
        $courses = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/courses.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function courseCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $title), '-'));
            $subtitle = trim($_POST['subtitle'] ?? '');
            $description = trim($_POST['description'] ?? '');
            $categoryId = $_POST['category_id'] ?: null;
            $levelId = $_POST['level_id'] ?: null;
            $duration = (int)($_POST['duration_hours'] ?? 0);
            $passMark = (int)($_POST['pass_mark'] ?? 50);
            $certEligible = isset($_POST['certificate_eligible']) ? 1 : 0;
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            $isFeatured = isset($_POST['is_featured']) ? 1 : 0;
            
            if (empty($title)) {
                $error = 'Course title is required.';
            } else {
                $this->pdo->prepare("INSERT INTO courses (category_id, level_id, title, slug, subtitle, description, duration_hours, pass_mark, certificate_eligible, is_published, is_featured, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")->execute([$categoryId, $levelId, $title, $slug, $subtitle, $description, $duration, $passMark, $certEligible, $isPublished, $isFeatured, current_user()['id']]);
                log_audit(current_user()['id'], 'course_create', 'course', $this->pdo->lastInsertId());
                flash('success', 'Course created successfully.');
                redirect(base_url('admin/courses'));
            }
        }
        
        $categories = $this->pdo->query("SELECT * FROM course_categories WHERE is_active = 1")->fetchAll();
        $levels = $this->pdo->query("SELECT * FROM course_levels ORDER BY sort_order")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/course_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function courseEdit($id) {
        $this->requireAdmin();
        $error = '';
        
        $stmt = $this->pdo->prepare("SELECT * FROM courses WHERE id = ?");
        $stmt->execute([$id]);
        $course = $stmt->fetch();
        if (!$course) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $title), '-'));
            $subtitle = trim($_POST['subtitle'] ?? '');
            $description = trim($_POST['description'] ?? '');
            $categoryId = $_POST['category_id'] ?: null;
            $levelId = $_POST['level_id'] ?: null;
            $duration = (int)($_POST['duration_hours'] ?? 0);
            $passMark = (int)($_POST['pass_mark'] ?? 50);
            $certEligible = isset($_POST['certificate_eligible']) ? 1 : 0;
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            $isFeatured = isset($_POST['is_featured']) ? 1 : 0;
            
            $this->pdo->prepare("UPDATE courses SET title=?, slug=?, subtitle=?, description=?, category_id=?, level_id=?, duration_hours=?, pass_mark=?, certificate_eligible=?, is_published=?, is_featured=? WHERE id=?")->execute([$title, $slug, $subtitle, $description, $categoryId, $levelId, $duration, $passMark, $certEligible, $isPublished, $isFeatured, $id]);
            log_audit(current_user()['id'], 'course_update', 'course', $id);
            flash('success', 'Course updated successfully.');
            redirect(base_url('admin/courses'));
        }
        
        $categories = $this->pdo->query("SELECT * FROM course_categories WHERE is_active = 1")->fetchAll();
        $levels = $this->pdo->query("SELECT * FROM course_levels ORDER BY sort_order")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/course_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== MODULES ==========
    public function modules($courseId = null) {
        $this->requireAdmin();
        
        if ($courseId) {
            $stmt = $this->pdo->prepare("SELECT * FROM courses WHERE id = ?");
            $stmt->execute([$courseId]);
            $course = $stmt->fetch();
            $stmt = $this->pdo->prepare("SELECT * FROM modules WHERE course_id = ? ORDER BY sort_order");
            $stmt->execute([$courseId]);
            $modules = $stmt->fetchAll();
        } else {
            $course = null;
            $modules = $this->pdo->query("SELECT m.*, c.title as course_title FROM modules m JOIN courses c ON m.course_id = c.id ORDER BY m.sort_order")->fetchAll();
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/modules.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function moduleCreate($courseId) {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $title), '-'));
            $description = trim($_POST['description'] ?? '');
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            
            if (empty($title)) {
                $error = 'Module title is required.';
            } else {
                $this->pdo->prepare("INSERT INTO modules (course_id, title, slug, description, sort_order, is_published) VALUES (?, ?, ?, ?, ?, ?)")->execute([$courseId, $title, $slug, $description, $sortOrder, $isPublished]);
                flash('success', 'Module created successfully.');
                redirect(base_url('admin/modules/' . $courseId));
            }
        }
        
        $stmt = $this->pdo->prepare("SELECT * FROM courses WHERE id = ?");
        $stmt->execute([$courseId]);
        $course = $stmt->fetch();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/module_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== LESSONS ==========
    public function lessons($moduleId) {
        $this->requireAdmin();
        
        $stmt = $this->pdo->prepare("SELECT m.*, c.id as course_id, c.title as course_title FROM modules m JOIN courses c ON m.course_id = c.id WHERE m.id = ?");
        $stmt->execute([$moduleId]);
        $module = $stmt->fetch();
        
        $stmt = $this->pdo->prepare("SELECT * FROM lessons WHERE module_id = ? ORDER BY sort_order");
        $stmt->execute([$moduleId]);
        $lessons = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/lessons.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function lessonCreate($moduleId) {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $title), '-'));
            $content = $_POST['content'] ?? '';
            $lessonType = $_POST['lesson_type'] ?? 'text';
            $videoUrl = trim($_POST['video_url'] ?? '');
            $externalUrl = trim($_POST['external_url'] ?? '');
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            $duration = (int)($_POST['duration_minutes'] ?? 0);
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            $isFree = isset($_POST['is_free']) ? 1 : 0;
            
            if (empty($title)) {
                $error = 'Lesson title is required.';
            } else {
                $this->pdo->prepare("INSERT INTO lessons (module_id, title, slug, content, lesson_type, video_url, external_url, sort_order, duration_minutes, is_published, is_free, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")->execute([$moduleId, $title, $slug, $content, $lessonType, $videoUrl, $externalUrl, $sortOrder, $duration, $isPublished, $isFree, current_user()['id']]);
                flash('success', 'Lesson created successfully.');
                $stmt = $this->pdo->prepare("SELECT course_id FROM modules WHERE id = ?");
                $stmt->execute([$moduleId]);
                redirect(base_url('admin/lessons/' . $moduleId));
            }
        }
        
        $stmt = $this->pdo->prepare("SELECT * FROM modules WHERE id = ?");
        $stmt->execute([$moduleId]);
        $module = $stmt->fetch();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/lesson_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== EXERCISES ==========
    public function exercises($moduleId = null) {
        $this->requireAdmin();
        
        if ($moduleId) {
            $stmt = $this->pdo->prepare("SELECT e.*, m.title as module_title, c.title as course_title FROM exercises e JOIN modules m ON e.module_id = m.id JOIN courses c ON m.course_id = c.id WHERE e.module_id = ? ORDER BY e.sort_order");
            $stmt->execute([$moduleId]);
            $exercises = $stmt->fetchAll();
            $stmt = $this->pdo->prepare("SELECT m.*, c.title as course_title FROM modules m JOIN courses c ON m.course_id = c.id WHERE m.id = ?");
            $stmt->execute([$moduleId]);
            $module = $stmt->fetch();
        } else {
            $module = null;
            $exercises = $this->pdo->query("SELECT e.*, m.title as module_title, c.title as course_title FROM exercises e JOIN modules m ON e.module_id = m.id JOIN courses c ON m.course_id = c.id ORDER BY e.sort_order")->fetchAll();
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/exercises.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function exerciseCreate($moduleId) {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $instructions = trim($_POST['instructions'] ?? '');
            $solution = trim($_POST['solution'] ?? '');
            $maxScore = (int)($_POST['max_score'] ?? 100);
            $passMark = (int)($_POST['pass_mark'] ?? 50);
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            
            if (empty($title) || empty($instructions)) {
                $error = 'Title and instructions are required.';
            } else {
                $this->pdo->prepare("INSERT INTO exercises (module_id, title, instructions, solution, max_score, pass_mark, sort_order, is_published) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")->execute([$moduleId, $title, $instructions, $solution, $maxScore, $passMark, $sortOrder, $isPublished]);
                flash('success', 'Exercise created successfully.');
                redirect(base_url('admin/exercises/' . $moduleId));
            }
        }
        
        $stmt = $this->pdo->prepare("SELECT m.*, c.title as course_title FROM modules m JOIN courses c ON m.course_id = c.id WHERE m.id = ?");
        $stmt->execute([$moduleId]);
        $module = $stmt->fetch();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/exercise_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== QUESTION BANK ==========
    public function questionBanks() {
        $this->requireAdmin();
        $banks = $this->pdo->query("SELECT qb.*, c.title as course_title, m.title as module_title FROM question_banks qb LEFT JOIN courses c ON qb.course_id = c.id LEFT JOIN modules m ON qb.module_id = m.id ORDER BY qb.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/question_banks.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function questionBankCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $name = trim($_POST['name'] ?? '');
            $description = trim($_POST['description'] ?? '');
            $category = trim($_POST['category'] ?? '');
            $difficulty = $_POST['difficulty'] ?? 'medium';
            $courseId = $_POST['course_id'] ?: null;
            $moduleId = $_POST['module_id'] ?: null;
            
            if (empty($name)) {
                $error = 'Bank name is required.';
            } else {
                $this->pdo->prepare("INSERT INTO question_banks (name, description, category, difficulty, course_id, module_id, created_by, is_public) VALUES (?, ?, ?, ?, ?, ?, ?, 1)")->execute([$name, $description, $category, $difficulty, $courseId, $moduleId, current_user()['id']]);
                flash('success', 'Question bank created.');
                redirect(base_url('admin/question-banks'));
            }
        }
        
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/question_bank_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function questionBankView($bankId) {
        $this->requireAdmin();
        
        $stmt = $this->pdo->prepare("SELECT * FROM question_banks WHERE id = ?");
        $stmt->execute([$bankId]);
        $bank = $stmt->fetch();
        if (!$bank) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        $stmt = $this->pdo->prepare("SELECT q.*, GROUP_CONCAT(qo.id, '|', qo.option_text, '|', qo.is_correct, '|', qo.sort_order SEPARATOR ';;') as options_raw FROM questions q LEFT JOIN question_options qo ON q.id = qo.question_id WHERE q.bank_id = ? GROUP BY q.id ORDER BY q.created_at DESC");
        $stmt->execute([$bankId]);
        $questions = $stmt->fetchAll();
        
        foreach ($questions as &$q) {
            $q['options'] = [];
            if ($q['options_raw']) {
                $parts = explode(';;', $q['options_raw']);
                foreach ($parts as $p) {
                    $o = explode('|', $p);
                    if (count($o) >= 3) {
                        $q['options'][] = ['id' => $o[0], 'option_text' => $o[1], 'is_correct' => $o[2], 'sort_order' => $o[3] ?? 0];
                    }
                }
            }
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/question_bank_view.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function questionCreate($bankId) {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $type = $_POST['question_type'] ?? 'multiple_choice';
            $text = trim($_POST['question_text'] ?? '');
            $explanation = trim($_POST['explanation'] ?? '');
            $difficulty = $_POST['difficulty'] ?? 'medium';
            $points = (int)($_POST['points'] ?? 1);
            $tags = trim($_POST['tags'] ?? '');
            
            if (empty($text)) {
                $error = 'Question text is required.';
            } else {
                $this->pdo->prepare("INSERT INTO questions (bank_id, question_type, question_text, explanation, difficulty, points, tags, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")->execute([$bankId, $type, $text, $explanation, $difficulty, $points, $tags, current_user()['id']]);
                $questionId = $this->pdo->lastInsertId();
                
                if ($type === 'multiple_choice' || $type === 'true_false') {
                    $optionTexts = $_POST['option_text'] ?? [];
                    $correctIndex = $_POST['correct_option'] ?? 0;
                    foreach ($optionTexts as $i => $optText) {
                        $isCorrect = ($i == $correctIndex) ? 1 : 0;
                        $this->pdo->prepare("INSERT INTO question_options (question_id, option_text, is_correct, sort_order) VALUES (?, ?, ?, ?)")->execute([$questionId, trim($optText), $isCorrect, $i + 1]);
                    }
                }
                
                flash('success', 'Question added successfully.');
                redirect(base_url('admin/question-bank/' . $bankId));
            }
        }
        
        $stmt = $this->pdo->prepare("SELECT * FROM question_banks WHERE id = ?");
        $stmt->execute([$bankId]);
        $bank = $stmt->fetch();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/question_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== CBT TESTS ==========
    public function tests() {
        $this->requireAdmin();
        $tests = $this->pdo->query("SELECT t.*, c.title as course_title, m.title as module_title FROM tests t LEFT JOIN courses c ON t.course_id = c.id LEFT JOIN modules m ON t.module_id = m.id ORDER BY t.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/tests.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function testCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $courseId = (int)($_POST['course_id'] ?? 0);
            $moduleId = $_POST['module_id'] ?: null;
            $description = trim($_POST['description'] ?? '');
            $testType = $_POST['test_type'] ?? 'cbt';
            $duration = (int)($_POST['duration_minutes'] ?? 60);
            $passMark = (int)($_POST['pass_mark'] ?? 50);
            $maxAttempts = (int)($_POST['max_attempts'] ?? 3);
            $questionsPerTest = (int)($_POST['questions_per_test'] ?? 20);
            $randomizeQ = isset($_POST['randomize_questions']) ? 1 : 0;
            $randomizeA = isset($_POST['randomize_answers']) ? 1 : 0;
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            
            if (empty($title) || empty($courseId)) {
                $error = 'Title and course are required.';
            } else {
                $this->pdo->prepare("INSERT INTO tests (course_id, module_id, title, description, test_type, duration_minutes, pass_mark, max_attempts, questions_per_test, randomize_questions, randomize_answers, is_published, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")->execute([$courseId, $moduleId, $title, $description, $testType, $duration, $passMark, $maxAttempts, $questionsPerTest, $randomizeQ, $randomizeA, $isPublished, current_user()['id']]);
                flash('success', 'Test created successfully.');
                redirect(base_url('admin/tests'));
            }
        }
        
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/test_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== ASSIGNMENTS ==========
    public function assignments() {
        $this->requireAdmin();
        $assignments = $this->pdo->query("SELECT a.*, c.title as course_title, m.title as module_title FROM assignments a LEFT JOIN courses c ON a.course_id = c.id LEFT JOIN modules m ON a.module_id = m.id ORDER BY a.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/assignments.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function assignmentCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $courseId = (int)($_POST['course_id'] ?? 0);
            $moduleId = $_POST['module_id'] ?: null;
            $description = trim($_POST['description'] ?? '');
            $instructions = trim($_POST['instructions'] ?? '');
            $maxScore = (int)($_POST['max_score'] ?? 100);
            $passMark = (int)($_POST['pass_mark'] ?? 50);
            $dueDate = $_POST['due_date'] ?: null;
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            
            if (empty($title) || empty($courseId)) {
                $error = 'Title and course are required.';
            } else {
                $this->pdo->prepare("INSERT INTO assignments (course_id, module_id, title, description, instructions, max_score, pass_mark, due_date, is_published, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")->execute([$courseId, $moduleId, $title, $description, $instructions, $maxScore, $passMark, $dueDate, $isPublished, current_user()['id']]);
                flash('success', 'Assignment created successfully.');
                redirect(base_url('admin/assignments'));
            }
        }
        
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/assignment_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== ENROLLMENTS ==========
    public function enrollments() {
        $this->requireAdmin();
        $search = $_GET['search'] ?? '';
        
        $where = "WHERE 1=1";
        $params = [];
        if ($search) { $where .= " AND (s.student_number LIKE ? OR u.first_name LIKE ? OR u.last_name LIKE ? OR c.title LIKE ?)"; $s = "%$search%"; $params = array_merge($params, [$s, $s, $s, $s]); }
        
        $stmt = $this->pdo->prepare("SELECT e.*, s.student_number, u.first_name, u.last_name, c.title as course_title, p.name as package_name FROM enrollments e JOIN students s ON e.student_id = s.id JOIN users u ON s.user_id = u.id JOIN courses c ON e.course_id = c.id LEFT JOIN packages p ON e.package_id = p.id $where ORDER BY e.enrolled_at DESC LIMIT 50");
        $stmt->execute($params);
        $enrollments = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/enrollments.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== PAYMENTS ==========
    public function payments() {
        $this->requireAdmin();
        $status = $_GET['status'] ?? '';
        $search = $_GET['search'] ?? '';
        
        $where = "WHERE 1=1";
        $params = [];
        if ($status) { $where .= " AND p.status = ?"; $params[] = $status; }
        if ($search) { $where .= " AND (s.student_number LIKE ? OR u.first_name LIKE ? OR u.last_name LIKE ?)"; $s = "%$search%"; $params = array_merge($params, [$s, $s, $s]); }
        
        $stmt = $this->pdo->prepare("SELECT p.*, s.student_number, u.first_name, u.last_name, pk.name as package_name FROM payments p JOIN students s ON p.student_id = s.id JOIN users u ON s.user_id = u.id LEFT JOIN packages pk ON p.package_id = pk.id $where ORDER BY p.created_at DESC LIMIT 50");
        $stmt->execute($params);
        $payments = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/payments.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function paymentView($id) {
        $this->requireAdmin();
        
        $stmt = $this->pdo->prepare("SELECT p.*, s.student_number, s.id as sid, u.first_name, u.last_name, u.email, pk.name as package_name FROM payments p JOIN students s ON p.student_id = s.id JOIN users u ON s.user_id = u.id LEFT JOIN packages pk ON p.package_id = pk.id WHERE p.id = ?");
        $stmt->execute([$id]);
        $payment = $stmt->fetch();
        if (!$payment) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        $stmt = $this->pdo->prepare("SELECT * FROM payment_proofs WHERE payment_id = ? ORDER BY created_at DESC");
        $stmt->execute([$id]);
        $proofs = $stmt->fetchAll();
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $action = $_POST['action'] ?? '';
            $notes = trim($_POST['notes'] ?? '');
            
            if ($action === 'approve') {
                $this->pdo->prepare("UPDATE payments SET status = 'approved', approved_by = ?, approved_at = NOW(), notes = ? WHERE id = ?")->execute([current_user()['id'], $notes, $id]);
                $this->pdo->prepare("UPDATE students SET payment_status = 'approved', enrollment_status = 'active' WHERE id = ?")->execute([$payment['sid']]);
                
                if ($payment['package_id']) {
                    $pkg = $this->pdo->prepare("SELECT * FROM packages WHERE id = ?");
                    $pkg->execute([$payment['package_id']]);
                    $package = $pkg->fetch();
                    $expiresAt = $package ? date('Y-m-d H:i:s', strtotime('+' . $package['duration_days'] . ' days')) : null;
                    
                    $courses = $this->pdo->prepare("SELECT course_id FROM package_courses WHERE package_id = ?");
                    $courses->execute([$payment['package_id']]);
                    while ($course = $courses->fetch()) {
                        $this->pdo->prepare("INSERT INTO enrollments (student_id, course_id, package_id, status, expires_at) VALUES (?, ?, ?, 'active', ?)")->execute([$payment['sid'], $course['course_id'], $payment['package_id'], $expiresAt]);
                    }
                }
                
                $body = '<h2>Payment Approved</h2><p>Dear ' . e($payment['first_name']) . ',</p><p>Your payment has been approved and your enrollment has been activated. You can now access your course materials.</p><p>Login: ' . base_url('login') . '</p>';
                send_email($payment['email'], 'Your Payment Has Been Approved - CIX Orbit Academy', $body);
                
                log_audit(current_user()['id'], 'payment_approve', 'payment', $id);
                flash('success', 'Payment approved and enrollment activated.');
            } elseif ($action === 'reject') {
                $this->pdo->prepare("UPDATE payments SET status = 'rejected', approved_by = ?, rejection_reason = ? WHERE id = ?")->execute([current_user()['id'], $notes, $id]);
                $this->pdo->prepare("UPDATE students SET payment_status = 'rejected' WHERE id = ?")->execute([$payment['sid']]);
                log_audit(current_user()['id'], 'payment_reject', 'payment', $id);
                flash('success', 'Payment rejected.');
            }
            redirect(base_url('admin/payment/' . $id));
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/payment_view.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== CERTIFICATES ==========
    public function certificates() {
        $this->requireAdmin();
        $certificates = $this->pdo->query("SELECT c.*, s.student_number, u.first_name, u.last_name, cr.title as course_title FROM certificates c JOIN students s ON c.student_id = s.id JOIN users u ON s.user_id = u.id JOIN courses cr ON c.course_id = cr.id ORDER BY c.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/certificates.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== ANNOUNCEMENTS ==========
    public function announcements() {
        $this->requireAdmin();
        $announcements = $this->pdo->query("SELECT a.*, u.first_name, u.last_name FROM announcements a LEFT JOIN users u ON a.created_by = u.id ORDER BY a.is_pinned DESC, a.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/announcements.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function announcementCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $content = trim($_POST['content'] ?? '');
            $targetRoles = $_POST['target_roles'] ?? [];
            $isPinned = isset($_POST['is_pinned']) ? 1 : 0;
            $expiresAt = $_POST['expires_at'] ?: null;
            
            if (empty($title) || empty($content)) {
                $error = 'Title and content are required.';
            } else {
                $this->pdo->prepare("INSERT INTO announcements (title, content, target_roles, is_pinned, expires_at, created_by) VALUES (?, ?, ?, ?, ?, ?)")->execute([$title, $content, json_encode($targetRoles), $isPinned, $expiresAt, current_user()['id']]);
                flash('success', 'Announcement created.');
                redirect(base_url('admin/announcements'));
            }
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/announcement_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== SUPPORT TICKETS ==========
    public function supportTickets() {
        $this->requireAdmin();
        $status = $_GET['status'] ?? '';
        
        $where = "WHERE 1=1";
        $params = [];
        if ($status) { $where .= " AND t.status = ?"; $params[] = $status; }
        
        $stmt = $this->pdo->prepare("SELECT t.*, u.first_name, u.last_name, s.student_number FROM support_tickets t LEFT JOIN users u ON t.user_id = u.id LEFT JOIN students s ON t.student_id = s.id $where ORDER BY t.created_at DESC LIMIT 50");
        $stmt->execute($params);
        $tickets = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/support_tickets.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== PACKAGES ==========
    public function packages() {
        $this->requireAdmin();
        $packages = $this->pdo->query("SELECT p.*, (SELECT COUNT(*) FROM package_courses WHERE package_id = p.id) as course_count FROM packages p ORDER BY p.sort_order")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/packages.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function packageCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $name = trim($_POST['name'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $name), '-'));
            $description = trim($_POST['description'] ?? '');
            $price = (float)($_POST['price'] ?? 0);
            $duration = (int)($_POST['duration_days'] ?? 365);
            $trialDays = (int)($_POST['trial_days'] ?? 0);
            $maxCourses = (int)($_POST['max_courses'] ?? 1);
            $certEligible = isset($_POST['certificate_eligible']) ? 1 : 0;
            $assessmentRequired = isset($_POST['assessment_required']) ? 1 : 0;
            $approvalType = $_POST['approval_type'] ?? 'manual';
            $isActive = isset($_POST['is_active']) ? 1 : 0;
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            
            if (empty($name)) {
                $error = 'Package name is required.';
            } else {
                $this->pdo->prepare("INSERT INTO packages (name, slug, description, price, duration_days, trial_days, max_courses, certificate_eligible, assessment_required, approval_type, is_active, sort_order) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")->execute([$name, $slug, $description, $price, $duration, $trialDays, $maxCourses, $certEligible, $assessmentRequired, $approvalType, $isActive, $sortOrder]);
                
                $packageId = $this->pdo->lastInsertId();
                $courseIds = $_POST['course_ids'] ?? [];
                foreach ($courseIds as $cid) {
                    $this->pdo->prepare("INSERT INTO package_courses (package_id, course_id) VALUES (?, ?)")->execute([$packageId, $cid]);
                }
                
                flash('success', 'Package created.');
                redirect(base_url('admin/packages'));
            }
        }
        
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/package_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== USERS & ROLES ==========
    public function users() {
        $this->requireAdmin();
        $users = $this->pdo->query("SELECT u.*, r.name as role_name, r.slug as role_slug FROM users u JOIN roles r ON u.role_id = r.id ORDER BY u.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/users.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function userCreate() {
        $this->requireAdmin();
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $firstName = trim($_POST['first_name'] ?? '');
            $lastName = trim($_POST['last_name'] ?? '');
            $email = trim($_POST['email'] ?? '');
            $phone = trim($_POST['phone'] ?? '');
            $roleId = (int)($_POST['role_id'] ?? 6);
            $password = $_POST['password'] ?? '';
            
            if (empty($firstName) || empty($lastName) || empty($email) || empty($password)) {
                $error = 'Please fill all required fields.';
            } else {
                $stmt = $this->pdo->prepare("SELECT id FROM users WHERE email = ?");
                $stmt->execute([$email]);
                if ($stmt->fetch()) {
                    $error = 'Email already exists.';
                } else {
                    $hash = password_hash($password, PASSWORD_DEFAULT);
                    $this->pdo->prepare("INSERT INTO users (role_id, first_name, last_name, email, phone, password_hash, is_active, email_verified_at) VALUES (?, ?, ?, ?, ?, ?, 1, NOW())")->execute([$roleId, $firstName, $lastName, $email, $phone, $hash]);
                    log_audit(current_user()['id'], 'user_create', 'user', $this->pdo->lastInsertId());
                    flash('success', 'User created.');
                    redirect(base_url('admin/users'));
                }
            }
        }
        
        $roles = $this->pdo->query("SELECT * FROM roles ORDER BY name")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/user_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    public function roles() {
        $this->requireAdmin();
        $roles = $this->pdo->query("SELECT r.*, (SELECT COUNT(*) FROM role_permissions WHERE role_id = r.id) as perm_count, (SELECT COUNT(*) FROM users WHERE role_id = r.id) as user_count FROM roles r ORDER BY r.name")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/roles.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== REPORTS ==========
    public function reports() {
        $this->requireAdmin();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/reports.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== AUDIT LOGS ==========
    public function auditLogs() {
        $this->requireAdmin();
        $page = max(1, (int)($_GET['page'] ?? 1));
        $perPage = 50;
        
        $total = $this->pdo->query("SELECT COUNT(*) FROM audit_logs")->fetchColumn();
        $pagination = paginate($total, $perPage, $page);
        
        $logs = $this->pdo->prepare("SELECT al.*, u.first_name, u.last_name FROM audit_logs al LEFT JOIN users u ON al.user_id = u.id ORDER BY al.created_at DESC LIMIT $perPage OFFSET {$pagination['offset']}");
        $logs->execute();
        $logs = $logs->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/audit_logs.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== SETTINGS ==========
    public function settings() {
        $this->requireAdmin();
        $success = '';
        $error = '';
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $section = $_POST['section'] ?? 'general';
            
            if ($section === 'general') {
                update_setting('academy_name', trim($_POST['academy_name'] ?? ''));
                update_setting('company_name', trim($_POST['company_name'] ?? ''));
                update_setting('academy_url', trim($_POST['academy_url'] ?? ''));
                update_setting('office_phone', trim($_POST['office_phone'] ?? ''));
                update_setting('whatsapp_number', trim($_POST['whatsapp_number'] ?? ''));
                update_setting('academic_email', trim($_POST['academic_email'] ?? ''));
                update_setting('slogan', trim($_POST['slogan'] ?? ''));
                update_setting('timezone', trim($_POST['timezone'] ?? 'Africa/Johannesburg'));
            } elseif ($section === 'smtp') {
                $host = trim($_POST['smtp_host'] ?? '');
                $port = (int)($_POST['smtp_port'] ?? 587);
                $username = trim($_POST['smtp_username'] ?? '');
                $password = trim($_POST['smtp_password'] ?? '');
                $encryption = $_POST['smtp_encryption'] ?? 'tls';
                $fromEmail = trim($_POST['smtp_from_email'] ?? '');
                $fromName = trim($_POST['smtp_from_name'] ?? '');
                
                if ($host && $username) {
                    $this->pdo->exec("UPDATE smtp_settings SET is_active = 0");
                    $stmt = $this->pdo->prepare("SELECT id FROM smtp_settings WHERE host = ? AND username = ?");
                    $stmt->execute([$host, $username]);
                    $existingId = $stmt->fetchColumn();
                    if ($existingId) {
                        if ($password !== '') {
                            $this->pdo->prepare("UPDATE smtp_settings SET port = ?, password_encrypted = ?, encryption = ?, from_email = ?, from_name = ?, is_active = 1 WHERE id = ?")->execute([$port, encrypt_secret($password), $encryption, $fromEmail, $fromName, $existingId]);
                        } else {
                            $this->pdo->prepare("UPDATE smtp_settings SET port = ?, encryption = ?, from_email = ?, from_name = ?, is_active = 1 WHERE id = ?")->execute([$port, $encryption, $fromEmail, $fromName, $existingId]);
                        }
                    } else {
                        $this->pdo->prepare("INSERT INTO smtp_settings (host, port, username, password_encrypted, encryption, from_email, from_name, is_active) VALUES (?, ?, ?, ?, ?, ?, ?, 1)")->execute([$host, $port, $username, encrypt_secret($password), $encryption, $fromEmail, $fromName]);
                    }
                }
            } elseif ($section === 'smtp_test') {
                $service = new \App\Services\EmailService($this->pdo);
                $result = $service->testConnection();
                $status = !empty($result['success']) ? 'success' : 'failed';
                $message = $result['message'] ?? $result['error'] ?? 'Unknown result';
                $this->pdo->prepare("UPDATE smtp_settings SET last_test_status = ?, last_test_message = ?, last_test_at = NOW() WHERE is_active = 1")->execute([$status, $message]);
                flash($status === 'success' ? 'success' : 'error', $message);
                redirect(base_url('admin/settings'));
            } elseif ($section === 'theme') {
                $themeId = (int)($_POST['theme_id'] ?? 1);
                $this->pdo->prepare("UPDATE themes SET is_default = 0 WHERE is_default = 1")->execute();
                $this->pdo->prepare("UPDATE themes SET is_default = 1 WHERE id = ?")->execute([$themeId]);
                $theme = $this->pdo->prepare("SELECT slug FROM themes WHERE id = ?");
                $theme->execute([$themeId]);
                $slug = $theme->fetchColumn();
                update_setting('default_theme', $slug);
                update_setting('admin_default_theme', trim($_POST['admin_default_theme'] ?? $slug));
                update_setting('teacher_default_theme', trim($_POST['teacher_default_theme'] ?? $slug));
                update_setting('student_default_theme', trim($_POST['student_default_theme'] ?? $slug));
                update_setting('public_default_theme', trim($_POST['public_default_theme'] ?? $slug));
            } elseif ($section === 'banking') {
                $this->pdo->exec("DELETE FROM banking_details");
                $stmt = $this->pdo->prepare("INSERT INTO banking_details (bank_name, account_name, account_number, branch_code, instructions, is_active, sort_order) VALUES (?, ?, ?, ?, ?, 1, ?)");
                $instruction = trim($_POST['payment_instruction'] ?? '');
                foreach (($_POST['banks'] ?? []) as $index => $bank) {
                    if (trim($bank['bank_name'] ?? '') === '') continue;
                    $stmt->execute([trim($bank['bank_name']), trim($bank['account_name'] ?? ''), trim($bank['account_number'] ?? ''), trim($bank['branch_code'] ?? ''), $instruction, $index + 1]);
                }
                update_setting('payment_instruction', $instruction);
            }
            
            log_audit(current_user()['id'], 'settings_update', 'settings', 0, null, ['section' => $section]);
            flash('success', 'Settings updated successfully.');
            redirect(base_url('admin/settings'));
        }
        
        $settings = [];
        $stmt = $this->pdo->query("SELECT * FROM settings ORDER BY setting_key");
        while ($row = $stmt->fetch()) { $settings[$row['setting_key']] = $row['setting_value']; }
        
        $smtp = $this->pdo->query("SELECT * FROM smtp_settings WHERE is_active = 1 LIMIT 1")->fetch();
        $themes = $this->pdo->query("SELECT * FROM themes ORDER BY name")->fetchAll();
        $currentTheme = $this->pdo->query("SELECT id FROM themes WHERE is_default = 1")->fetchColumn();
        $bankDetails = $this->pdo->query("SELECT * FROM banking_details WHERE is_active = 1 ORDER BY sort_order, id")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/settings.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== SYSTEM HEALTH ==========
    public function systemHealth() {
        $this->requireAdmin();
        $info = [
            'php_version' => PHP_VERSION,
            'mysql_version' => $this->pdo->query("SELECT VERSION()")->fetchColumn(),
            'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
            'memory_limit' => ini_get('memory_limit'),
            'upload_max' => ini_get('upload_max_filesize'),
            'post_max' => ini_get('post_max_filesize'),
            'max_execution' => ini_get('max_execution_time'),
            'disk_free' => function_exists('disk_free_space') ? @disk_free_space('/') : 'N/A',
            'extensions' => [
                'pdo' => extension_loaded('pdo'),
                'pdo_mysql' => extension_loaded('pdo_mysql'),
                'mbstring' => extension_loaded('mbstring'),
                'json' => extension_loaded('json'),
                'gd' => extension_loaded('gd'),
                'zip' => extension_loaded('zip'),
                'curl' => extension_loaded('curl'),
                'openssl' => extension_loaded('openssl'),
            ]
        ];
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/system_health.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== BACKUP ==========
    public function backup() {
        $this->requireAdmin();
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $dbName = defined('DB_NAME') ? constant('DB_NAME') : '';
            $backupDir = __DIR__ . '/../../storage/backups';
            if (!is_dir($backupDir)) mkdir($backupDir, 0755, true);
            
            $filename = 'backup_' . date('Y-m-d_His') . '.sql';
            $filepath = $backupDir . '/' . $filename;
            
            $tables = $this->pdo->prepare("SHOW TABLES");
            $tables->execute();
            $tables = $tables->fetchAll(\PDO::FETCH_COLUMN);
            
            $sql = "-- CIX Orbit Academy Backup\n-- Date: " . date('Y-m-d H:i:s') . "\n\n";
            foreach ($tables as $table) {
                $sql .= "DROP TABLE IF EXISTS `$table`;\n";
                $create = $this->pdo->prepare("SHOW CREATE TABLE `$table`");
                $create->execute();
                $row = $create->fetch();
                $sql .= $row[1] . ";\n\n";
                
                $data = $this->pdo->query("SELECT * FROM `$table`")->fetchAll();
                foreach ($data as $row) {
                    $values = array_map(function($v) { return $v === null ? 'NULL' : "'" . addslashes($v) . "'"; }, $row);
                    $sql .= "INSERT INTO `$table` VALUES (" . implode(', ', $values) . ");\n";
                }
                $sql .= "\n";
            }
            
            file_put_contents($filepath, $sql);
            $this->pdo->prepare("INSERT INTO backups (file_name, file_path, file_size, backup_type, created_by) VALUES (?, ?, ?, 'full', ?)")->execute([$filename, $filepath, filesize($filepath), current_user()['id']]);
            log_audit(current_user()['id'], 'backup_create', 'backup', 0);
            flash('success', 'Backup created: ' . $filename);
            redirect(base_url('admin/backup'));
        }
        
        $backups = $this->pdo->query("SELECT b.*, u.first_name, u.last_name FROM backups b LEFT JOIN users u ON b.created_by = u.id ORDER BY b.created_at DESC")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/backup.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== AI SETTINGS ==========
    public function aiSettings() {
        $this->requireAdmin();
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $name = trim($_POST['name'] ?? '');
            $baseUrl = trim($_POST['base_url'] ?? '');
            $apiKey = trim($_POST['api_key'] ?? '');
            $model = trim($_POST['model'] ?? '');
            $temperature = (float)($_POST['temperature'] ?? 0.7);
            $maxTokens = (int)($_POST['max_tokens'] ?? 1000);
            $isActive = isset($_POST['is_active']) ? 1 : 0;
            $isDefault = isset($_POST['is_default']) ? 1 : 0;
            
            if ($isDefault) {
                $this->pdo->exec("UPDATE ai_providers SET is_default = 0");
            }
            
            $editId = (int)($_POST['edit_id'] ?? 0);
            if ($editId) {
                $this->pdo->prepare("UPDATE ai_providers SET name=?, base_url=?, api_key_encrypted=?, model=?, temperature=?, max_tokens=?, is_active=?, is_default=? WHERE id=?")->execute([$name, $baseUrl, $apiKey, $model, $temperature, $maxTokens, $isActive, $isDefault, $editId]);
            } else {
                $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $name), '-'));
                $this->pdo->prepare("INSERT INTO ai_providers (name, slug, base_url, api_key_encrypted, model, temperature, max_tokens, is_active, is_default) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")->execute([$name, $slug, $baseUrl, $apiKey, $model, $temperature, $maxTokens, $isActive, $isDefault]);
            }
            
            flash('success', 'AI provider saved.');
            redirect(base_url('admin/ai-settings'));
        }
        
        $providers = $this->pdo->query("SELECT * FROM ai_providers ORDER BY name")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/ai_settings.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== THEMES ==========
    public function themes() {
        $this->requireAdmin();
        $themes = $this->pdo->query("SELECT * FROM themes ORDER BY name")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/themes.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }
    
    // ========== GLOBAL SEARCH ==========
    public function search() {
        $this->requireAdmin();
        $query = trim($_GET['q'] ?? '');
        $results = [];
        
        if ($query) {
            $s = "%$query%";
            $results['students'] = $this->pdo->prepare("SELECT s.*, u.first_name, u.last_name, u.email FROM students s JOIN users u ON s.user_id = u.id WHERE s.student_number LIKE ? OR u.first_name LIKE ? OR u.last_name LIKE ? OR u.email LIKE ? LIMIT 10");
            $results['students']->execute([$s, $s, $s, $s]);
            $results['students'] = $results['students']->fetchAll();
            
            $results['certificates'] = $this->pdo->prepare("SELECT c.*, s.student_number FROM certificates c JOIN students s ON c.student_id = s.id WHERE c.certificate_number LIKE ? OR c.student_name LIKE ? LIMIT 10");
            $results['certificates']->execute([$s, $s]);
            $results['certificates'] = $results['certificates']->fetchAll();
            
            $results['courses'] = $this->pdo->prepare("SELECT * FROM courses WHERE title LIKE ? OR description LIKE ? LIMIT 10");
            $results['courses']->execute([$s, $s]);
            $results['courses'] = $results['courses']->fetchAll();
        }
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/search.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== MODULE EDIT ==========
    public function moduleEdit($moduleId) {
        $this->requireAdmin();
        $error = '';
        $stmt = $this->pdo->prepare("SELECT m.*, c.id as course_id, c.title as course_title FROM modules m JOIN courses c ON m.course_id = c.id WHERE m.id = ?");
        $stmt->execute([$moduleId]);
        $module = $stmt->fetch();
        if (!$module) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $title), '-'));
            $description = trim($_POST['description'] ?? '');
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            if (empty($title)) { $error = 'Module title is required.'; }
            else {
                $this->pdo->prepare("UPDATE modules SET title=?, slug=?, description=?, sort_order=?, is_published=? WHERE id=?")->execute([$title, $slug, $description, $sortOrder, $isPublished, $moduleId]);
                log_audit(current_user()['id'], 'module_update', 'module', $moduleId);
                flash('success', 'Module updated.');
                redirect(base_url('admin/modules/' . $module['course_id']));
            }
        }
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/module_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== LESSON EDIT ==========
    public function lessonEdit($lessonId) {
        $this->requireAdmin();
        $error = '';
        $stmt = $this->pdo->prepare("SELECT l.*, m.id as module_id, m.course_id, m.title as module_title FROM lessons l JOIN modules m ON l.module_id = m.id WHERE l.id = ?");
        $stmt->execute([$lessonId]);
        $lesson = $stmt->fetch();
        if (!$lesson) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $title), '-'));
            $content = $_POST['content'] ?? '';
            $lessonType = $_POST['lesson_type'] ?? 'text';
            $videoUrl = trim($_POST['video_url'] ?? '');
            $externalUrl = trim($_POST['external_url'] ?? '');
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            $duration = (int)($_POST['duration_minutes'] ?? 0);
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            if (empty($title)) { $error = 'Lesson title is required.'; }
            else {
                $this->pdo->prepare("UPDATE lessons SET title=?, slug=?, content=?, lesson_type=?, video_url=?, external_url=?, sort_order=?, duration_minutes=?, is_published=? WHERE id=?")->execute([$title, $slug, $content, $lessonType, $videoUrl, $externalUrl, $sortOrder, $duration, $isPublished, $lessonId]);
                log_audit(current_user()['id'], 'lesson_update', 'lesson', $lessonId);
                flash('success', 'Lesson updated.');
                redirect(base_url('admin/modules/' . $lesson['course_id']));
            }
        }
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/lesson_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== TEST VIEW ==========
    public function testView($testId) {
        $this->requireAdmin();
        $stmt = $this->pdo->prepare("SELECT t.*, c.title as course_title FROM tests t LEFT JOIN courses c ON t.course_id = c.id WHERE t.id = ?");
        $stmt->execute([$testId]);
        $test = $stmt->fetch();
        if (!$test) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        $stmt = $this->pdo->prepare("SELECT ts.*, qb.name as bank_name, qb.id as bank_id FROM test_sections ts LEFT JOIN question_banks qb ON ts.bank_id = qb.id WHERE ts.test_id = ? ORDER BY ts.sort_order");
        $stmt->execute([$testId]);
        $sections = $stmt->fetchAll();
        
        $stmt = $this->pdo->prepare("SELECT ta.*, s.student_number, u.first_name, u.last_name FROM test_attempts ta JOIN students s ON ta.student_id = s.id JOIN users u ON s.user_id = u.id WHERE ta.test_id = ? ORDER BY ta.created_at DESC LIMIT 50");
        $stmt->execute([$testId]);
        $attempts = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/test_view.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== TEST EDIT ==========
    public function testEdit($testId) {
        $this->requireAdmin();
        $error = '';
        $stmt = $this->pdo->prepare("SELECT * FROM tests WHERE id = ?");
        $stmt->execute([$testId]);
        $test = $stmt->fetch();
        if (!$test) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['title'] ?? '');
            $description = trim($_POST['description'] ?? '');
            $duration = (int)($_POST['duration_minutes'] ?? 60);
            $passMark = (int)($_POST['pass_mark'] ?? 50);
            $maxAttempts = (int)($_POST['max_attempts'] ?? 3);
            $questionsPerTest = (int)($_POST['questions_per_test'] ?? 20);
            $randomizeQ = isset($_POST['randomize_questions']) ? 1 : 0;
            $randomizeA = isset($_POST['randomize_answers']) ? 1 : 0;
            $isPublished = isset($_POST['is_published']) ? 1 : 0;
            $certificateTrigger = isset($_POST['certificate_trigger']) ? 1 : 0;
            
            if (empty($title)) { $error = 'Title is required.'; }
            else {
                $this->pdo->prepare("UPDATE tests SET title=?, description=?, duration_minutes=?, pass_mark=?, max_attempts=?, questions_per_test=?, randomize_questions=?, randomize_answers=?, is_published=?, certificate_trigger=? WHERE id=?")->execute([$title, $description, $duration, $passMark, $maxAttempts, $questionsPerTest, $randomizeQ, $randomizeA, $isPublished, $certificateTrigger, $testId]);
                log_audit(current_user()['id'], 'test_update', 'test', $testId);
                flash('success', 'Test updated.');
                redirect(base_url('admin/tests'));
            }
        }
        
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1")->fetchAll();
        $banks = $this->pdo->query("SELECT id, name FROM question_banks ORDER BY name")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/test_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== TEST SECTIONS ==========
    public function testSections($testId) {
        $this->requireAdmin();
        $stmt = $this->pdo->prepare("SELECT * FROM tests WHERE id = ?");
        $stmt->execute([$testId]);
        $test = $stmt->fetch();
        if (!$test) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $title = trim($_POST['section_title'] ?? '');
            $bankId = (int)($_POST['bank_id'] ?? 0);
            $questionCount = (int)($_POST['question_count'] ?? 10);
            $difficulty = $_POST['difficulty_filter'] ?? 'all';
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            
            if (empty($title) || empty($bankId)) { flash('error', 'Title and bank are required.'); }
            else {
                $this->pdo->prepare("INSERT INTO test_sections (test_id, bank_id, title, question_count, difficulty_filter, sort_order) VALUES (?, ?, ?, ?, ?, ?)")->execute([$testId, $bankId, $title, $questionCount, $difficulty, $sortOrder]);
                log_audit(current_user()['id'], 'test_section_add', 'test', $testId);
                flash('success', 'Section added.');
            }
            redirect(base_url('admin/test-sections/' . $testId));
        }
        
        $stmt = $this->pdo->prepare("SELECT ts.*, qb.name as bank_name FROM test_sections ts LEFT JOIN question_banks qb ON ts.bank_id = qb.id WHERE ts.test_id = ? ORDER BY ts.sort_order");
        $stmt->execute([$testId]);
        $sections = $stmt->fetchAll();
        $banks = $this->pdo->query("SELECT id, name FROM question_banks ORDER BY name")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/test_sections.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== ENROLLMENT CREATE ==========
    public function enrollmentCreate() {
        $this->requireAdmin();
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $studentId = (int)($_POST['student_id'] ?? 0);
            $courseId = (int)($_POST['course_id'] ?? 0);
            $packageId = $_POST['package_id'] ?: null;
            
            if (empty($studentId) || empty($courseId)) { flash('error', 'Student and course are required.'); }
            else {
                $stmt = $this->pdo->prepare("SELECT id FROM enrollments WHERE student_id = ? AND course_id = ? AND status = 'active'");
                $stmt->execute([$studentId, $courseId]);
                if ($stmt->fetch()) { flash('error', 'Student is already enrolled in this course.'); }
                else {
                    $expiresAt = null;
                    if ($packageId) {
                        $pkg = $this->pdo->prepare("SELECT duration_days FROM packages WHERE id = ?");
                        $pkg->execute([$packageId]);
                        $days = $pkg->fetchColumn();
                        if ($days) $expiresAt = date('Y-m-d H:i:s', strtotime("+{$days} days"));
                    }
                    $this->pdo->prepare("INSERT INTO enrollments (student_id, course_id, package_id, status, expires_at) VALUES (?, ?, ?, 'active', ?)")->execute([$studentId, $courseId, $packageId, $expiresAt]);
                    log_audit(current_user()['id'], 'enrollment_create', 'enrollment', $this->pdo->lastInsertId());
                    flash('success', 'Enrollment created.');
                }
            }
            redirect(base_url('admin/enrollments'));
        }
        $students = $this->pdo->query("SELECT s.id, s.student_number, u.first_name, u.last_name FROM students s JOIN users u ON s.user_id = u.id ORDER BY u.last_name")->fetchAll();
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1 ORDER BY title")->fetchAll();
        $packages = $this->pdo->query("SELECT id, name FROM packages WHERE is_active = 1 ORDER BY sort_order")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/enrollment_create.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== PACKAGE EDIT ==========
    public function packageEdit($id) {
        $this->requireAdmin();
        $error = '';
        $stmt = $this->pdo->prepare("SELECT * FROM packages WHERE id = ?");
        $stmt->execute([$id]);
        $package = $stmt->fetch();
        if (!$package) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $name = trim($_POST['name'] ?? '');
            $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/', '-', $name), '-'));
            $description = trim($_POST['description'] ?? '');
            $price = (float)($_POST['price'] ?? 0);
            $duration = (int)($_POST['duration_days'] ?? 365);
            $trialDays = (int)($_POST['trial_days'] ?? 0);
            $maxCourses = (int)($_POST['max_courses'] ?? 1);
            $certEligible = isset($_POST['certificate_eligible']) ? 1 : 0;
            $assessmentRequired = isset($_POST['assessment_required']) ? 1 : 0;
            $approvalType = $_POST['approval_type'] ?? 'manual';
            $isActive = isset($_POST['is_active']) ? 1 : 0;
            $sortOrder = (int)($_POST['sort_order'] ?? 0);
            
            if (empty($name)) { $error = 'Name is required.'; }
            else {
                $this->pdo->prepare("UPDATE packages SET name=?, slug=?, description=?, price=?, duration_days=?, trial_days=?, max_courses=?, certificate_eligible=?, assessment_required=?, approval_type=?, is_active=?, sort_order=? WHERE id=?")->execute([$name, $slug, $description, $price, $duration, $trialDays, $maxCourses, $certEligible, $assessmentRequired, $approvalType, $isActive, $sortOrder, $id]);
                $this->pdo->prepare("DELETE FROM package_courses WHERE package_id = ?")->execute([$id]);
                $courseIds = $_POST['course_ids'] ?? [];
                foreach ($courseIds as $cid) { $this->pdo->prepare("INSERT INTO package_courses (package_id, course_id) VALUES (?, ?)")->execute([$id, $cid]); }
                log_audit(current_user()['id'], 'package_update', 'package', $id);
                flash('success', 'Package updated.');
                redirect(base_url('admin/packages'));
            }
        }
        $selectedCourses = $this->pdo->prepare("SELECT course_id FROM package_courses WHERE package_id = ?");
        $selectedCourses->execute([$id]);
        $selectedCourseIds = $selectedCourses->fetchAll(\PDO::FETCH_COLUMN);
        $courses = $this->pdo->query("SELECT id, title FROM courses WHERE is_published = 1")->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/package_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    public function packageDelete($id) {
        $this->requireAdmin();
        $this->pdo->prepare("DELETE FROM packages WHERE id = ?")->execute([$id]);
        log_audit(current_user()['id'], 'package_delete', 'package', $id);
        flash('success', 'Package deleted.');
        redirect(base_url('admin/packages'));
    }

    // ========== USER EDIT ==========
    public function userEdit($id) {
        $this->requireAdmin();
        $error = '';
        $stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$id]);
        $userEdit = $stmt->fetch();
        if (!$userEdit) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $firstName = trim($_POST['first_name'] ?? '');
            $lastName = trim($_POST['last_name'] ?? '');
            $email = trim($_POST['email'] ?? '');
            $phone = trim($_POST['phone'] ?? '');
            $roleId = (int)($_POST['role_id'] ?? 6);
            $isActive = isset($_POST['is_active']) ? 1 : 0;
            $newPassword = trim($_POST['new_password'] ?? '');
            
            if (empty($firstName) || empty($lastName) || empty($email)) { $error = 'Required fields cannot be empty.'; }
            else {
                if ($newPassword) {
                    $hash = password_hash($newPassword, PASSWORD_DEFAULT);
                    $this->pdo->prepare("UPDATE users SET first_name=?, last_name=?, email=?, phone=?, role_id=?, is_active=?, password_hash=? WHERE id=?")->execute([$firstName, $lastName, $email, $phone, $roleId, $isActive, $hash, $id]);
                } else {
                    $this->pdo->prepare("UPDATE users SET first_name=?, last_name=?, email=?, phone=?, role_id=?, is_active=? WHERE id=?")->execute([$firstName, $lastName, $email, $phone, $roleId, $isActive, $id]);
                }
                log_audit(current_user()['id'], 'user_update', 'user', $id);
                flash('success', 'User updated.');
                redirect(base_url('admin/users'));
            }
        }
        $roles = $this->pdo->query("SELECT * FROM roles ORDER BY name")->fetchAll();
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/user_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    public function userToggle($id) {
        $this->requireAdmin();
        $user = $this->pdo->prepare("SELECT is_active FROM users WHERE id = ?");
        $user->execute([$id]);
        $current = $user->fetchColumn();
        $this->pdo->prepare("UPDATE users SET is_active = ? WHERE id = ?")->execute([$current ? 0 : 1, $id]);
        log_audit(current_user()['id'], 'user_toggle', 'user', $id);
        flash('success', 'User status updated.');
        redirect(base_url('admin/users'));
    }

    // ========== REPORT GENERATION ==========
    public function reportStudent($studentId) {
        $this->requireAdmin();
        $service = new \App\Services\PdfService($this->pdo);
        $filepath = $service->generateStudentReport($studentId);
        if ($filepath && file_exists($filepath)) {
            header('Content-Type: application/pdf');
            header('Content-Disposition: inline; filename="student-report-' . $studentId . '.pdf"');
            readfile($filepath);
            exit;
        }
        flash('error', 'Failed to generate report.');
        redirect(base_url('admin/student/' . $studentId));
    }

    public function reportClass($courseId) {
        $this->requireAdmin();
        $service = new \App\Services\PdfService($this->pdo);
        $filepath = $service->generateClassReport($courseId);
        if ($filepath && file_exists($filepath)) {
            header('Content-Type: application/pdf');
            header('Content-Disposition: inline; filename="class-report-' . $courseId . '.pdf"');
            readfile($filepath);
            exit;
        }
        flash('error', 'Failed to generate report.');
        redirect(base_url('admin/courses'));
    }

    public function reportPayments() {
        $this->requireAdmin();
        $service = new \App\Services\PdfService($this->pdo);
        $filepath = $service->generatePaymentReport();
        if ($filepath && file_exists($filepath)) {
            header('Content-Type: application/pdf');
            header('Content-Disposition: inline; filename="payment-report.pdf"');
            readfile($filepath);
            exit;
        }
        flash('error', 'Failed to generate report.');
        redirect(base_url('admin/reports'));
    }

    public function reportCertificates() {
        $this->requireAdmin();
        $service = new \App\Services\PdfService($this->pdo);
        $filepath = $service->generateCertificateReport();
        if ($filepath && file_exists($filepath)) {
            header('Content-Type: application/pdf');
            header('Content-Disposition: inline; filename="certificate-report.pdf"');
            readfile($filepath);
            exit;
        }
        flash('error', 'Failed to generate report.');
        redirect(base_url('admin/reports'));
    }

    public function reportApplications() {
        $this->requireAdmin();
        $service = new \App\Services\PdfService($this->pdo);
        $filepath = $service->generateApplicationReport();
        if ($filepath && file_exists($filepath)) {
            header('Content-Type: application/pdf');
            header('Content-Disposition: inline; filename="application-report.pdf"');
            readfile($filepath);
            exit;
        }
        flash('error', 'Failed to generate report.');
        redirect(base_url('admin/reports'));
    }

    // ========== CSV EXPORTS ==========
    public function exportStudents() {
        $this->requireAdmin();
        $stmt = $this->pdo->query("SELECT s.student_number, u.first_name, u.last_name, u.email, u.phone, s.province, s.town, s.enrollment_status, s.payment_status, s.created_at FROM students s JOIN users u ON s.user_id = u.id ORDER BY s.created_at DESC");
        $students = $stmt->fetchAll();
        $headers = ['Student Number', 'First Name', 'Last Name', 'Email', 'Phone', 'Province', 'Town', 'Enrollment Status', 'Payment Status', 'Created'];
        $data = array_map(function($s) { return $s; }, $students);
        export_csv($data, $headers, 'students-' . date('Ymd') . '.csv');
    }

    public function exportApplications() {
        $this->requireAdmin();
        $stmt = $this->pdo->query("SELECT first_name, last_name, email, phone, province, town, highest_education, status, created_at FROM applications ORDER BY created_at DESC");
        $apps = $stmt->fetchAll();
        $headers = ['First Name', 'Last Name', 'Email', 'Phone', 'Province', 'Town', 'Education', 'Status', 'Date'];
        export_csv($apps, $headers, 'applications-' . date('Ymd') . '.csv');
    }

    public function exportPayments() {
        $this->requireAdmin();
        $stmt = $this->pdo->query("SELECT s.student_number, u.first_name, u.last_name, p.amount, p.status, p.created_at FROM payments p JOIN students s ON p.student_id = s.id JOIN users u ON s.user_id = u.id ORDER BY p.created_at DESC");
        $payments = $stmt->fetchAll();
        $headers = ['Student Number', 'First Name', 'Last Name', 'Amount', 'Status', 'Date'];
        export_csv($payments, $headers, 'payments-' . date('Ymd') . '.csv');
    }

    public function exportResults() {
        $this->requireAdmin();
        $stmt = $this->pdo->query("SELECT s.student_number, u.first_name, u.last_name, t.title as test_title, c.title as course_title, ta.score, ta.max_score, ta.pass_mark, ta.passed, ta.ended_at FROM test_attempts ta JOIN students s ON ta.student_id = s.id JOIN users u ON s.user_id = u.id JOIN tests t ON ta.test_id = t.id JOIN courses c ON t.course_id = c.id WHERE ta.status = 'completed' ORDER BY ta.ended_at DESC");
        $results = $stmt->fetchAll();
        $headers = ['Student Number', 'First Name', 'Last Name', 'Test', 'Course', 'Score', 'Max Score', 'Pass Mark', 'Passed', 'Date'];
        export_csv($results, $headers, 'results-' . date('Ymd') . '.csv');
    }

    // ========== EMAIL TEMPLATES ==========
    public function emailTemplates() {
        $this->requireAdmin();
        $templates = $this->pdo->query("SELECT * FROM email_templates ORDER BY code")->fetchAll();
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/email_templates.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    public function emailTemplateEdit($id) {
        $this->requireAdmin();
        $error = '';
        $stmt = $this->pdo->prepare("SELECT * FROM email_templates WHERE id = ?");
        $stmt->execute([$id]);
        $template = $stmt->fetch();
        if (!$template) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $subject = trim($_POST['subject'] ?? '');
            $body = $_POST['body'] ?? '';
            $isActive = isset($_POST['is_active']) ? 1 : 0;
            $this->pdo->prepare("UPDATE email_templates SET subject=?, body=?, is_active=?, updated_at=NOW() WHERE id=?")->execute([$subject, $body, $isActive, $id]);
            log_audit(current_user()['id'], 'email_template_update', 'email_template', $id);
            flash('success', 'Template updated.');
            redirect(base_url('admin/email-templates'));
        }
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/email_template_edit.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    public function sendTestEmail() {
        $this->requireAdmin();
        $email = trim($_POST['email'] ?? current_user()['email']);
        $service = new \App\Services\EmailService($this->pdo);
        $result = $service->send($email, 'CIX Orbit Academy - SMTP Test', '<h3>SMTP Test</h3><p>Your email configuration is working correctly. This is a test email from CIX Orbit Academy.</p><p>Sent at: ' . date('d M Y H:i:s') . '</p>');
        if ($result) { flash('success', 'Test email sent to ' . $email); }
        else { flash('error', 'Failed to send test email. Check SMTP settings.'); }
        redirect(base_url('admin/settings'));
    }

    // ========== SUPPORT TICKET VIEW ==========
    public function supportTicketView($id) {
        $this->requireAdmin();
        $stmt = $this->pdo->prepare("SELECT t.*, u.first_name, u.last_name, u.email, s.student_number FROM support_tickets t LEFT JOIN users u ON t.user_id = u.id LEFT JOIN students s ON t.student_id = s.id WHERE t.id = ?");
        $stmt->execute([$id]);
        $ticket = $stmt->fetch();
        if (!$ticket) { http_response_code(404); require_once __DIR__ . '/../Views/errors/404.php'; exit; }
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST' && verify_csrf($_POST['csrf_token'] ?? '')) {
            $action = $_POST['action'] ?? '';
            if ($action === 'reply') {
                $message = trim($_POST['message'] ?? '');
                if (!empty($message)) {
                    $this->pdo->prepare("INSERT INTO support_replies (ticket_id, user_id, message) VALUES (?, ?, ?)")->execute([$id, current_user()['id'], $message]);
                    $this->pdo->prepare("UPDATE tickets SET status = 'in_progress' WHERE id = ? AND status = 'open'")->execute([$id]);
                }
            } elseif ($action === 'resolve') {
                $this->pdo->prepare("UPDATE support_tickets SET status = 'resolved', resolved_at = NOW() WHERE id = ?")->execute([$id]);
            } elseif ($action === 'close') {
                $this->pdo->prepare("UPDATE support_tickets SET status = 'closed' WHERE id = ?")->execute([$id]);
            }
            log_audit(current_user()['id'], 'support_ticket_' . $action, 'support_ticket', $id);
            flash('success', 'Ticket updated.');
            redirect(base_url('admin/support-tickets/' . $id));
        }
        
        $stmt = $this->pdo->prepare("SELECT sr.*, u.first_name, u.last_name FROM support_replies sr JOIN users u ON sr.user_id = u.id WHERE sr.ticket_id = ? ORDER BY sr.created_at ASC");
        $stmt->execute([$id]);
        $replies = $stmt->fetchAll();
        
        include __DIR__ . '/../Views/layouts/admin.php';
        include __DIR__ . '/../Views/admin/support_ticket_view.php';
        include __DIR__ . '/../Views/layouts/footer.php';
    }

    // ========== CACHE CLEAR ==========
    public function cacheClear() {
        $this->requireAdmin();
        $cacheDir = dirname(__DIR__, 2) . '/storage/cache';
        if (is_dir($cacheDir)) {
            $files = glob($cacheDir . '/*.cache');
            foreach ($files as $file) @unlink($file);
        }
        log_audit(current_user()['id'], 'cache_clear', 'system', 0);
        flash('success', 'Cache cleared. (' . count($files ?? []) . ' files removed)');
        redirect(base_url('admin/settings'));
    }
}
