<?php
require_once APP_PATH . '/Core/BaseController.php';
require_once APP_PATH . '/Models/Notification.php';
require_once APP_PATH . '/Core/CSRF.php';
require_once APP_PATH . '/Core/JaasHelper.php';

class SessionController extends BaseController {

    public function index(): void {
        $db   = Database::getInstance();
        $userId = Auth::id();
        $role   = Auth::role();

        if ($role === 'student') {
            $stmt = $db->prepare(
                "SELECT s.*, u.first_name AS mentor_first, u.last_name AS mentor_last, u.avatar AS mentor_avatar
                 FROM sessions s JOIN users u ON u.id = s.mentor_id
                 WHERE s.student_id = ? ORDER BY s.scheduled_at DESC"
            );
        } else {
            $stmt = $db->prepare(
                "SELECT s.*, u.first_name AS student_first, u.last_name AS student_last, u.avatar AS student_avatar
                 FROM sessions s JOIN users u ON u.id = s.student_id
                 WHERE s.mentor_id = ? ORDER BY s.scheduled_at DESC"
            );
        }
        $stmt->execute([$userId]);
        $sessions = $stmt->fetchAll();

        $this->view('sessions.index', [
            'title'    => 'Sessions — BOAFO',
            'sessions' => $sessions,
        ]);
    }

    public function bookForm(string $mentorId): void {
        $db   = Database::getInstance();
        $stmt = $db->prepare(
            "SELECT mp.*, u.first_name, u.last_name, u.avatar, uni.name AS university_name
             FROM mentor_profiles mp JOIN users u ON u.id = mp.user_id
             LEFT JOIN universities uni ON uni.id = mp.university_id
             WHERE mp.user_id = ?"
        );
        $stmt->execute([(int)$mentorId]);
        $mentor = $stmt->fetch();

        if (!$mentor) {
            $this->flash('error', 'Mentor not found.');
            $this->back();
        }

        $this->view('sessions.book', [
            'title'  => 'Book Session — BOAFO',
            'mentor' => $mentor,
        ]);
    }

    public function availableSlots(): void {
        $mentorId = (int)$_GET['mentor_id'] ?? 0;
        $date     = $_GET['date'] ?? '';

        if (!$mentorId || !$date || !strtotime($date)) {
            $this->json(['success' => false, 'slots' => []]);
        }

        $timestamp = strtotime($date);
        $dayOfWeek = (int)date('w', $timestamp);

        $db = Database::getInstance();
        
        // 1. Get Mentor Availability
        $stmt = $db->prepare("SELECT start_time, end_time FROM user_availability WHERE user_id = ? AND day_of_week = ? ORDER BY start_time ASC");
        $stmt->execute([$mentorId, $dayOfWeek]);
        $avails = $stmt->fetchAll();

        if (empty($avails)) {
            $this->json(['success' => true, 'slots' => []]);
        }

        // 2. Get Booked Sessions
        $stmt2 = $db->prepare(
            "SELECT scheduled_at, duration_min FROM sessions 
             WHERE mentor_id = ? AND DATE(scheduled_at) = ? AND status IN ('pending', 'confirmed')"
        );
        $stmt2->execute([$mentorId, $date]);
        $booked = $stmt2->fetchAll();

        // 3. Generate 60-min slots for all availability blocks
        $slots = [];
        $slotDuration = 60 * 60; // 60 mins
        $now = time();

        foreach ($avails as $avail) {
            $start = strtotime($date . ' ' . $avail['start_time']);
            $end   = strtotime($date . ' ' . $avail['end_time']);
            $current = $start;

            while ($current + $slotDuration <= $end) {
                $slotStart = $current;
                $slotEnd   = $current + $slotDuration;
                
                // Skip slots in the past
                if ($slotStart <= $now) {
                    $current += $slotDuration;
                    continue;
                }

                $isAvailable = true;
                foreach ($booked as $b) {
                    $bStart = strtotime($b['scheduled_at']);
                    $bEnd   = $bStart + ($b['duration_min'] * 60);

                    // Overlap condition: slotStart < bEnd AND slotEnd > bStart
                    if ($slotStart < $bEnd && $slotEnd > $bStart) {
                        $isAvailable = false;
                        break;
                    }
                }

                if ($isAvailable) {
                    $slots[] = date('H:i', $slotStart);
                }

                $current += $slotDuration; // move to next 60-min slot
            }
        }

        // Deduplicate and sort slots (just in case blocks overlap)
        $slots = array_unique($slots);
        sort($slots);

        $this->json(['success' => true, 'slots' => $slots]);
    }

    public function book(): void {
        CSRF::check();

        $db       = Database::getInstance();
        $studentId= Auth::id();
        $mentorId = (int) $this->input('mentor_id', 0);
        $title    = $this->sanitize($this->input('title', 'Mentorship Session'));
        $desc     = $this->sanitize($this->input('description', ''));
        $type     = $this->input('session_type', 'mentorship');
        $date     = $this->input('scheduled_date', '');
        $time     = $this->input('scheduled_time', '');
        $duration = (int) $this->input('duration_min', 60);

        $scheduledAt = $date . ' ' . $time . ':00';
        $timestamp = strtotime($scheduledAt);

        if ($timestamp < time()) {
            $this->flash('error', 'Please select a future date and time.');
            $this->back();
        }

        // Check availability
        $slotStart = $timestamp;
        $slotEnd = $timestamp + ($duration * 60);

        $stmtOverlap = $db->prepare(
            "SELECT id FROM sessions WHERE mentor_id = ? AND DATE(scheduled_at) = ? AND status IN ('pending', 'confirmed') 
             AND ((UNIX_TIMESTAMP(scheduled_at) < ?) AND (UNIX_TIMESTAMP(scheduled_at) + (duration_min * 60) > ?))"
        );
        $stmtOverlap->execute([$mentorId, $date, $slotEnd, $slotStart]);
        if ($stmtOverlap->fetch()) {
            $this->flash('error', 'The selected time slot is already booked.');
            $this->back();
        }

        $stmt = $db->prepare(
            "INSERT INTO sessions (student_id, mentor_id, title, description, session_type, scheduled_at, duration_min)
             VALUES (?, ?, ?, ?, ?, ?, ?)"
        );
        $stmt->execute([$studentId, $mentorId, $title, $desc, $type, $scheduledAt, $duration]);

        $notifModel = new Notification();
        $student    = Auth::user();
        $notifModel->send(
            $mentorId, 'session_request',
            'New Session Request',
            "{$student['name']} wants to book a session on " . formatDateTime($scheduledAt),
            APP_URL . '/sessions'
        );

        $this->flash('success', 'Session booked! Waiting for mentor confirmation.');
        $this->redirect(APP_URL . '/sessions');
    }

    public function confirm(string $id): void {
        CSRF::check();
        $db = Database::getInstance();
        // Store the internal room name (used for JWT and routing)
        $roomName = JaasHelper::roomName((int)$id);
        
        $stmt = $db->prepare("UPDATE sessions SET status = 'confirmed', meeting_link = ? WHERE id = ? AND mentor_id = ?");
        $stmt->execute([$roomName, (int)$id, Auth::id()]);

        // Notify student
        $stmt2 = $db->prepare("SELECT s.*, u.id AS student_user_id FROM sessions s JOIN users u ON u.id = s.student_id WHERE s.id = ?");
        $stmt2->execute([(int)$id]);
        $session = $stmt2->fetch();
        if ($session) {
            $notif = new Notification();
            $notif->send(
                $session['student_user_id'], 'session_confirmed', 'Session Confirmed',
                'Your session on ' . formatDateTime($session['scheduled_at']) . ' has been confirmed! Join via BOAFO.',
                APP_URL . '/sessions'
            );
        }

        if ($this->isAjax()) $this->json(['success'=>true]);
        $this->flash('success', 'Session confirmed! Your video room is ready.');
        $this->redirect(APP_URL . '/sessions');
    }

    /** ──────────────────────────────────────────
     *  In-App Video Meeting
     * ────────────────────────────────────────── */
    public function meeting(string $id): void {
        $db     = Database::getInstance();
        $userId = Auth::id();
        $role   = Auth::role();

        // Load session and verify authorization
        $stmt = $db->prepare(
            "SELECT s.*,
                    m.first_name AS mentor_first, m.last_name AS mentor_last, m.email AS mentor_email,
                    st.first_name AS student_first, st.last_name AS student_last, st.email AS student_email
             FROM sessions s
             JOIN users m  ON m.id  = s.mentor_id
             JOIN users st ON st.id = s.student_id
             WHERE s.id = ? AND (s.mentor_id = ? OR s.student_id = ?)"
        );
        $stmt->execute([(int)$id, $userId, $userId]);
        $session = $stmt->fetch();

        if (!$session) {
            $this->flash('error', 'Session not found or you are not authorised to join.');
            $this->redirect(APP_URL . '/sessions');
        }

        if ($session['status'] !== 'confirmed') {
            $this->flash('error', 'This session has not been confirmed yet.');
            $this->redirect(APP_URL . '/sessions');
        }

        $isModerator = in_array($role, ['mentor', 'tutor', 'admin']);
        $roomName    = $session['meeting_link'] ?: JaasHelper::roomName((int)$id);

        $currentUser = Auth::user();
        $currentUser['name'] = trim(($currentUser['first_name'] ?? '') . ' ' . ($currentUser['last_name'] ?? ''));

        // Generate JWT
        try {
            $jwt = JaasHelper::generateToken(
                [
                    'id'     => $userId,
                    'name'   => $currentUser['name'],
                    'email'  => $currentUser['email'],
                    'avatar' => !empty($currentUser['avatar']) ? UPLOAD_URL . '/' . $currentUser['avatar'] : '',
                ],
                $roomName,
                $isModerator
            );
        } catch (\Throwable $e) {
            $jwt = ''; // Will fall back to anonymous mode in the view
        }

        // Render without main layout (full-screen)
        $this->view('sessions.meeting', [
            'title'       => $session['title'] . ' — BOAFO Meeting',
            'session'     => $session,
            'roomName'    => $roomName,
            'jwt'         => $jwt,
            'isModerator' => $isModerator,
            'currentUser' => $currentUser,
        ], null); // null = no layout
    }

    /** ──────────────────────────────────────────
     *  ICS Calendar Download
     * ────────────────────────────────────────── */
    public function ics(string $id): void {
        $db     = Database::getInstance();
        $userId = Auth::id();

        $stmt = $db->prepare(
            "SELECT s.*,
                    m.first_name AS mentor_first, m.last_name AS mentor_last,
                    st.first_name AS student_first, st.last_name AS student_last
             FROM sessions s
             JOIN users m  ON m.id  = s.mentor_id
             JOIN users st ON st.id = s.student_id
             WHERE s.id = ? AND (s.mentor_id = ? OR s.student_id = ?)"
        );
        $stmt->execute([(int)$id, $userId, $userId]);
        $session = $stmt->fetch();

        if (!$session) {
            $this->flash('error', 'Session not found.');
            $this->redirect(APP_URL . '/sessions');
        }

        $startTs   = strtotime($session['scheduled_at']);
        $endTs     = $startTs + ($session['duration_min'] * 60);
        $dtStart   = gmdate('Ymd\THis\Z', $startTs);
        $dtEnd     = gmdate('Ymd\THis\Z', $endTs);
        $dtStamp   = gmdate('Ymd\THis\Z');
        $uid       = 'BOAFO-session-' . $session['id'] . '@boafo.app';
        $meetingUrl = APP_URL . '/sessions/' . $session['id'] . '/meeting';

        $partnerName = Auth::isStudent()
            ? trim($session['mentor_first'] . ' ' . $session['mentor_last'])
            : trim($session['student_first'] . ' ' . $session['student_last']);

        $summary     = addcslashes($session['title'], ',;\\');
        $description = addcslashes('Join your BOAFO video session with ' . $partnerName . '. Meeting link: ' . $meetingUrl, ',;\\');
        $location    = addcslashes($meetingUrl, ',;\\');

        $ics = "BEGIN:VCALENDAR\r\n"
             . "VERSION:2.0\r\n"
             . "PRODID:-//BOAFO//Sessions//EN\r\n"
             . "CALSCALE:GREGORIAN\r\n"
             . "METHOD:PUBLISH\r\n"
             . "BEGIN:VEVENT\r\n"
             . "UID:{$uid}\r\n"
             . "DTSTAMP:{$dtStamp}\r\n"
             . "DTSTART:{$dtStart}\r\n"
             . "DTEND:{$dtEnd}\r\n"
             . "SUMMARY:{$summary}\r\n"
             . "DESCRIPTION:{$description}\r\n"
             . "LOCATION:{$location}\r\n"
             . "URL:{$meetingUrl}\r\n"
             . "STATUS:CONFIRMED\r\n"
             . "END:VEVENT\r\n"
             . "END:VCALENDAR\r\n";

        header('Content-Type: text/calendar; charset=utf-8');
        header('Content-Disposition: attachment; filename="boafo-session-' . (int)$id . '.ics"');
        header('Cache-Control: no-cache, must-revalidate');
        echo $ics;
        exit;
    }

    public function cancel(string $id): void {
        CSRF::check();
        $db = Database::getInstance();
        $userId = Auth::id();
        $stmt = $db->prepare(
            "UPDATE sessions SET status = 'cancelled' WHERE id = ? AND (student_id = ? OR mentor_id = ?)"
        );
        $stmt->execute([(int)$id, $userId, $userId]);

        if ($this->isAjax()) $this->json(['success'=>true]);
        $this->flash('success', 'Session cancelled.');
        $this->redirect(APP_URL . '/sessions');
    }

    public function done(string $id): void {
        CSRF::check();
        $db = Database::getInstance();
        $userId = Auth::id();
        $stmt = $db->prepare(
            "UPDATE sessions SET status = 'completed' WHERE id = ? AND (student_id = ? OR mentor_id = ?) AND status = 'confirmed'"
        );
        $stmt->execute([(int)$id, $userId, $userId]);

        if ($this->isAjax()) $this->json(['success'=>true]);
        $this->flash('success', 'Session marked as completed.');
        $this->redirect(APP_URL . '/sessions');
    }


    public function rate(string $id): void {
        CSRF::check();
        $db     = Database::getInstance();
        $rating  = (int) $this->input('rating', 5);
        $feedback= $this->sanitize($this->input('feedback', ''));

        $stmt = $db->prepare(
            "UPDATE sessions SET rating = ?, feedback = ?, status = 'completed' WHERE id = ? AND student_id = ?"
        );
        $stmt->execute([$rating, $feedback, (int)$id, Auth::id()]);

        // Update mentor rating
        $stmt2 = $db->prepare("SELECT mentor_id FROM sessions WHERE id = ?");
        $stmt2->execute([(int)$id]);
        $session = $stmt2->fetch();
        if ($session) {
            $db->prepare(
                "INSERT INTO mentor_reviews (mentor_id, student_id, session_id, rating, review) VALUES (?, ?, ?, ?, ?)"
            )->execute([$session['mentor_id'], Auth::id(), (int)$id, $rating, $feedback]);

            // Recalculate mentor rating
            $db->prepare(
                "UPDATE mentor_profiles SET rating = (SELECT AVG(rating) FROM mentor_reviews WHERE mentor_id = ?), sessions_completed = sessions_completed + 1 WHERE user_id = ?"
            )->execute([$session['mentor_id'], $session['mentor_id']]);
        }

        if ($this->isAjax()) $this->json(['success'=>true]);
        $this->flash('success', 'Session rated. Thank you for your feedback!');
        $this->redirect(APP_URL . '/sessions');
    }
}
