"""
Continuous Teaching Session Management System

This module handles:
1. Continuous creation of teaching sessions from active timetables
2. Session verification measures (10-minute rule)
3. Email alerts (1 hour before sessions)
4. Attendance tracking for ongoing sessions
"""

from datetime import datetime, timedelta, time
from src.models import DatabaseContextManager
from src.models.models import (
    TeachingSession, TimetableBlock, Timetable, Tutor,
    Enrollment, Attendance, AttendanceStatus, Reminder,
    NotificationPreference
)
from src.utils import send_email
import uuid
from typing import Dict, List
import threading
import time as time_module


class ContinuousSessionManager:
    """Manages continuous creation and monitoring of teaching sessions"""
    
    def __init__(self):
        self.session_manager = None  # Will be injected
        self.is_running = False
        self.monitor_thread = None
        
    def set_session_manager(self, session_manager):
        """Inject the TeachingSessionManager instance"""
        self.session_manager = session_manager
    
    def start_monitoring(self):
        """Start the continuous monitoring system"""
        if self.is_running:
            return
            
        self.is_running = True
        self.monitor_thread = threading.Thread(target=self._monitor_sessions, daemon=True)
        self.monitor_thread.start()
    
    def stop_monitoring(self):
        """Stop the continuous monitoring system"""
        self.is_running = False
        if self.monitor_thread:
            self.monitor_thread.join(timeout=5)
    
    def _monitor_sessions(self):
        """Main monitoring loop - runs every minute"""
        while self.is_running:
            try:
                # Create sessions for today
                self._create_daily_sessions()
                
                # Send 1-hour alerts
                self._send_session_alerts()
                
                # Check for sessions that should be started/ended
                self._update_session_statuses()
                
                # Sleep for 1 minute
                time_module.sleep(60)
                
            except Exception as e:
                time_module.sleep(60)  # Continue monitoring even if there's an error
    
    def _create_daily_sessions(self):
        """Create teaching sessions for today based on active timetables"""
        with DatabaseContextManager() as ctx:
            today = datetime.now().date()
            today_weekday = today.weekday()  # Monday=0, Sunday=6
            
            # Get all active timetables
            active_timetables = ctx.session.query(Timetable).filter(
                Timetable.is_active == True,
                Timetable.is_verified == True
            ).all()
            
            for timetable in active_timetables:
                # Get timetable blocks for today's weekday
                blocks = ctx.session.query(TimetableBlock).filter(
                    TimetableBlock.timetable_id == timetable.id,
                    TimetableBlock.day_of_week == today_weekday,
                    TimetableBlock.is_active == True
                ).all()
                
                for block in blocks:
                    # Check if session already exists for today
                    existing_session = ctx.session.query(TeachingSession).filter(
                        TeachingSession.timetable_id == timetable.id,
                        TeachingSession.course_id == block.course_id,
                        TeachingSession.tutor_id == block.tutor_id,
                        TeachingSession.day_of_week == today_weekday,
                        TeachingSession.start_time == block.start_time,
                        TeachingSession.end_time == block.end_time,
                        TeachingSession.created_at >= today,
                        TeachingSession.created_at < today + timedelta(days=1)
                    ).first()
                    
                    if not existing_session:
                        # Create new teaching session
                        session = TeachingSession(
                            id=str(uuid.uuid4()),
                            course_id=block.course_id,
                            tutor_id=block.tutor_id,
                            supervisor_tutor_id=block.supervisor_tutor_id,
                            timetable_id=timetable.id,
                            room=block.room or 'TBD',
                            day_of_week=today_weekday,
                            start_time=block.start_time,
                            end_time=block.end_time,
                            status='scheduled',
                            session_type=block.block_type or 'lecture',
                            recurring=False,  # Individual sessions are not recurring
                            notes=f"Auto-generated from timetable block {block.id}",
                            created_at=datetime.utcnow(),
                            updated_at=datetime.utcnow(),
                            created_by='system'
                        )
                        
                        ctx.session.add(session)
            
            ctx.session.commit()
    
    def _send_session_alerts(self):
        """Send email alerts at 30, 20, and 10 minutes before sessions start"""
        with DatabaseContextManager() as ctx:
            now = datetime.utcnow()
            
            # Define alert intervals (in minutes before session start)
            alert_intervals = [30, 20, 10]
            
            for minutes in alert_intervals:
                alert_time = now + timedelta(minutes=minutes)
                time_window_start = alert_time - timedelta(minutes=1)
                time_window_end = alert_time + timedelta(minutes=1)
                
                # Find sessions starting in the alert window
            upcoming_sessions = ctx.session.query(TeachingSession).filter(
                TeachingSession.status == 'scheduled',
                    TeachingSession.start_time >= time_window_start,
                    TeachingSession.start_time <= time_window_end
            ).all()
            
            for session in upcoming_sessions:
                    # Check if alert already sent for this time interval
                existing_reminder = ctx.session.query(Reminder).filter(
                    Reminder.session_id == session.id,
                        Reminder.reminder_type == f'session_alert_{minutes}min',
                    Reminder.sent_at >= now.date()
                ).first()
                
                if not existing_reminder:
                    # Send alert to tutor and students
                    self._send_session_alert(session, minutes)
                    
                    # Record reminder
                    reminder = Reminder(
                        id=str(uuid.uuid4()),
                        session_id=session.id,
                        reminder_type=f'session_alert_{minutes}min',
                        message=f"Session starting in {minutes} minutes: {session.course.title if session.course else 'Unknown Course'}",
                        sent_to=session.tutor_id,
                        sent_at=now,
                        status='sent'
                    )
                    ctx.session.add(reminder)
            
            ctx.session.commit()
    
    def _send_session_alert(self, session: TeachingSession, minutes_before: int):
        """Send email alerts to tutor and students about upcoming session"""
        with DatabaseContextManager() as ctx:
            # Send alert to tutor
            self._send_tutor_session_alert(session, minutes_before)
            
            # Send alerts to enrolled students
            self._send_student_session_alerts(session, minutes_before)
    
    def _send_tutor_session_alert(self, session: TeachingSession, minutes_before: int):
        """Send email alert to tutor about upcoming session"""
        with DatabaseContextManager() as ctx:
            tutor = ctx.session.query(Tutor).filter(
                Tutor.id == session.tutor_id
            ).first()
            
            if not tutor or not tutor.email:
                return
            
            # Check tutor's notification preferences
            tutor_prefs = ctx.session.query(NotificationPreference).filter(
                NotificationPreference.user_id == tutor.id
            ).first()
            
            if tutor_prefs and not tutor_prefs.receive_email:
                return
            
            # Determine urgency level and color
            if minutes_before <= 10:
                urgency_color = "#dc3545"  # Red for urgent
                urgency_text = "URGENT"
            elif minutes_before <= 20:
                urgency_color = "#fd7e14"  # Orange for warning
                urgency_text = "WARNING"
            else:
                urgency_color = "#ffc107"  # Yellow for notice
                urgency_text = "NOTICE"
            
            subject = f"{urgency_text}: Session Starting in {minutes_before} Minutes - {session.course.title if session.course else 'Teaching Session'}"
            
            message = f"""
            <html>
                <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
                    <div style="max-width: 600px; margin: 0 auto; padding: 20px;">
                        <div style="background-color: {urgency_color}; color: white; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 20px;">
                            <h2 style="margin: 0; font-size: 24px;">{urgency_text}</h2>
                            <p style="margin: 5px 0 0 0; font-size: 18px;">Session Starting in {minutes_before} Minutes</p>
                        </div>
                        
                        <h2 style="color: #2c3e50;">Teaching Session Reminder</h2>
                    <p>Hello {tutor.first_name},</p>
                    
                        <p>You have a teaching session starting in <strong>{minutes_before} minutes</strong>:</p>
                    
                        <div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; border-left: 4px solid {urgency_color};">
                            <h3 style="margin-top: 0; color: #2c3e50;">Session Details</h3>
                        <p><strong>Course:</strong> {session.course.title if session.course else 'Unknown Course'}</p>
                        <p><strong>Course Code:</strong> {session.course.code if session.course else 'N/A'}</p>
                        <p><strong>Start Time:</strong> {session.start_time.strftime('%H:%M')}</p>
                        <p><strong>End Time:</strong> {session.end_time.strftime('%H:%M')}</p>
                        <p><strong>Room:</strong> {session.room or 'TBD'}</p>
                            <p><strong>Session Type:</strong> {session.session_type.title()}</p>
                    </div>
                    
                        <div style="background-color: #e3f2fd; padding: 15px; border-radius: 8px; margin: 20px 0;">
                            <p><strong>⏰ Time Remaining:</strong> {minutes_before} minutes</p>
                            <p><strong>📚 Preparation:</strong> Please ensure you have all necessary materials ready</p>
                            <p><strong>📍 Location:</strong> Make sure you know the room location</p>
                        </div>
                        
                        <div style="text-align: center; margin: 30px 0;">
                        <a href="https://kisiwa.mutabletech.co.ke/sessions/{session.id}" 
                            style="background-color: #28a745; color: white; padding: 12px 25px; text-decoration: none; border-radius: 6px; font-weight: bold; display: inline-block;">
                            View Session Details
                        </a>
                    </div>
                    
                        <hr style="border: none; border-top: 1px solid #eee; margin: 30px 0;">
                        
                        <p style="font-size: 14px; color: #666;">
                            This is an automated reminder from the Kisiwa Timetable Management System.<br>
                            If you have any questions, please contact your supervisor.
                        </p>
                        
                        <p style="margin-top: 20px;">
                            Best regards,<br>
                            <strong>Kisiwa Tech Team</strong>
                        </p>
                    </div>
                </body>
            </html>
            """
            
            try:
                send_email(
                    sender_email='kisiwa@mutabletech.co.ke',
                    sender_password='z}Y{WN$jV=Sv',
                    receiver_email=tutor.email,
                    subject=subject,
                    message=message
                )
                print(f"✅ Sent {minutes_before}min alert to tutor: {tutor.email}")
            except Exception as e:
                print(f"❌ Failed to send alert to tutor: {e}")
    
    def _send_student_session_alerts(self, session: TeachingSession, minutes_before: int):
        """Send email alerts to enrolled students about upcoming session"""
        with DatabaseContextManager() as ctx:
            # Get enrolled students for this course
            enrollments = ctx.session.query(Enrollment).filter(
                Enrollment.course_id == session.course_id,
                Enrollment.status == 'active'
            ).all()
            
            for enrollment in enrollments:
                student = enrollment.student
                if not student or not student.email:
                    continue
                
                # Check student's notification preferences
                student_prefs = ctx.session.query(NotificationPreference).filter(
                    NotificationPreference.user_id == student.id
                ).first()
                
                if student_prefs and not student_prefs.receive_email:
                    continue
                
                # Determine urgency level and color
                if minutes_before <= 10:
                    urgency_color = "#dc3545"  # Red for urgent
                    urgency_text = "URGENT"
                elif minutes_before <= 20:
                    urgency_color = "#fd7e14"  # Orange for warning
                    urgency_text = "WARNING"
                else:
                    urgency_color = "#ffc107"  # Yellow for notice
                    urgency_text = "NOTICE"
                
                subject = f"{urgency_text}: Class Starting in {minutes_before} Minutes - {session.course.title if session.course else 'Class'}"
                
                message = f"""
                <html>
                    <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
                        <div style="max-width: 600px; margin: 0 auto; padding: 20px;">
                            <div style="background-color: {urgency_color}; color: white; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 20px;">
                                <h2 style="margin: 0; font-size: 24px;">{urgency_text}</h2>
                                <p style="margin: 5px 0 0 0; font-size: 18px;">Class Starting in {minutes_before} Minutes</p>
                            </div>
                            
                            <h2 style="color: #2c3e50;">Class Reminder</h2>
                            <p>Hello {student.first_name},</p>
                            
                            <p>You have a class starting in <strong>{minutes_before} minutes</strong>:</p>
                            
                            <div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; border-left: 4px solid {urgency_color};">
                                <h3 style="margin-top: 0; color: #2c3e50;">Class Details</h3>
                                <p><strong>Course:</strong> {session.course.title if session.course else 'Unknown Course'}</p>
                                <p><strong>Course Code:</strong> {session.course.code if session.course else 'N/A'}</p>
                                <p><strong>Start Time:</strong> {session.start_time.strftime('%H:%M')}</p>
                                <p><strong>End Time:</strong> {session.end_time.strftime('%H:%M')}</p>
                                <p><strong>Room:</strong> {session.room or 'TBD'}</p>
                                <p><strong>Instructor:</strong> {session.tutor.first_name} {session.tutor.last_name if session.tutor else 'TBD'}</p>
                                <p><strong>Class Type:</strong> {session.session_type.title()}</p>
                            </div>
                            
                            <div style="background-color: #e8f5e8; padding: 15px; border-radius: 8px; margin: 20px 0;">
                                <p><strong>⏰ Time Remaining:</strong> {minutes_before} minutes</p>
                                <p><strong>📚 Preparation:</strong> Bring your materials and be ready to learn</p>
                                <p><strong>📍 Location:</strong> Head to {session.room or 'the assigned room'}</p>
                            </div>
                            
                            <div style="text-align: center; margin: 30px 0;">
                                <a href="https://kisiwa.mutabletech.co.ke/sessions/{session.id}" 
                                style="background-color: #007bff; color: white; padding: 12px 25px; text-decoration: none; border-radius: 6px; font-weight: bold; display: inline-block;">
                                    View Class Details
                                </a>
                            </div>
                            
                            <hr style="border: none; border-top: 1px solid #eee; margin: 30px 0;">
                            
                            <p style="font-size: 14px; color: #666;">
                                This is an automated reminder from the Kisiwa Timetable Management System.<br>
                                If you have any questions, please contact your instructor or academic advisor.
                            </p>
                            
                            <p style="margin-top: 20px;">
                                Best regards,<br>
                                <strong>Kisiwa Tech Team</strong>
                            </p>
                        </div>
                    </body>
                </html>
                """
                
                try:
                    send_email(
                        sender_email='kisiwa@mutabletech.co.ke',
                        sender_password='z}Y{WN$jV=Sv',
                        receiver_email=student.email,
                        subject=subject,
                        message=message
                    )
                    print(f"✅ Sent {minutes_before}min alert to student: {student.email}")
                except Exception as e:
                    print(f"❌ Failed to send alert to student: {e}")
    
    def _update_session_statuses(self):
        """Update session statuses based on current time"""
        with DatabaseContextManager() as ctx:
            now = datetime.utcnow()
            
            # Update sessions that should be ongoing
            ongoing_sessions = ctx.session.query(TeachingSession).filter(
                TeachingSession.status == 'scheduled',
                TeachingSession.start_time <= now,
                TeachingSession.end_time >= now
            ).all()
            
            for session in ongoing_sessions:
                session.status = 'ongoing'
                session.updated_at = now
            
            # Update sessions that should be completed
            completed_sessions = ctx.session.query(TeachingSession).filter(
                TeachingSession.status == 'ongoing',
                TeachingSession.end_time < now
            ).all()
            
            for session in completed_sessions:
                session.status = 'completed'
                session.updated_at = now
            
            ctx.session.commit()
    
    def can_start_session(self, session_id: str) -> Dict:
        """
        Check if a session can be started based on verification rules
        
        Args:
            session_id: ID of the session to check
            
        Returns:
            Dict with can_start boolean and reason
        """
        with DatabaseContextManager() as ctx:
            session = ctx.session.query(TeachingSession).filter(
                TeachingSession.id == session_id
            ).first()
            
            if not session:
                return {
                    'can_start': False,
                    'reason': 'Session not found',
                    'error_code': 'SESSION_NOT_FOUND'
                }
            
            if session.status != 'scheduled':
                return {
                    'can_start': False,
                    'reason': f'Session status is {session.status}, not scheduled',
                    'error_code': 'INVALID_STATUS'
                }
            
            now = datetime.utcnow()
            session_start = datetime.combine(now.date(), session.start_time)
            
            # Check 10-minute rule
            ten_minutes_before = session_start - timedelta(minutes=10)
            
            if now < ten_minutes_before:
                return {
                    'can_start': False,
                    'reason': 'Session cannot be started more than 10 minutes before scheduled time',
                    'error_code': 'TOO_EARLY',
                    'earliest_start_time': ten_minutes_before.isoformat(),
                    'current_time': now.isoformat()
                }
            
            # Check if session has already ended
            session_end = datetime.combine(now.date(), session.end_time)
            if now > session_end:
                return {
                    'can_start': False,
                    'reason': 'Session has already ended',
                    'error_code': 'SESSION_ENDED',
                    'session_end_time': session_end.isoformat(),
                    'current_time': now.isoformat()
                }
            
            return {
                'can_start': True,
                'reason': 'Session can be started',
                'earliest_start_time': ten_minutes_before.isoformat(),
                'current_time': now.isoformat()
            }
    
    def get_attendance_for_ongoing_session(self, session_id: str) -> Dict:
        """
        Get attendance information for an ongoing session
        
        Args:
            session_id: ID of the session
            
        Returns:
            Dict with attendance data
        """
        with DatabaseContextManager() as ctx:
            session = ctx.session.query(TeachingSession).filter(
                TeachingSession.id == session_id
            ).first()
            
            if not session:
                return {
                    'success': False,
                    'message': 'Session not found'
                }
            
            if session.status not in ['ongoing', 'completed']:
                return {
                    'success': False,
                    'message': 'Session is not ongoing or completed'
                }
            
            # Get enrolled students
            enrollments = ctx.session.query(Enrollment).filter(
                Enrollment.course_id == session.course_id,
                Enrollment.status == 'active'
            ).all()
            
            # Get attendance records
            attendance_records = ctx.session.query(Attendance).filter(
                Attendance.session_id == session_id
            ).all()
            
            attendance_dict = {att.student_id: att for att in attendance_records}
            
            # Build attendance summary
            attendance_summary = {
                'session_id': session_id,
                'course_title': session.course.title if session.course else 'Unknown',
                'session_time': f"{session.start_time.strftime('%H:%M')} - {session.end_time.strftime('%H:%M')}",
                'total_enrolled': len(enrollments),
                'present': 0,
                'absent': 0,
                'late': 0,
                'excused': 0,
                'attendance_percentage': 0,
                'students': []
            }
            
            for enrollment in enrollments:
                student = enrollment.student
                attendance = attendance_dict.get(student.id)
                
                student_data = {
                    'student_id': student.id,
                    'student_name': f"{student.first_name} {student.last_name}",
                    'student_id_number': student.student_id,
                    'status': attendance.status.value if attendance else 'absent',
                    'timestamp': attendance.timestamp.isoformat() if attendance else None,
                    'late_minutes': attendance.late_minutes if attendance else None,
                    'notes': attendance.notes if attendance else None
                }
                
                # Update counters
                if attendance:
                    if attendance.status == AttendanceStatus.present:
                        attendance_summary['present'] += 1
                    elif attendance.status == AttendanceStatus.absent:
                        attendance_summary['absent'] += 1
                    elif attendance.status == AttendanceStatus.late:
                        attendance_summary['late'] += 1
                    elif attendance.status == AttendanceStatus.excused:
                        attendance_summary['excused'] += 1
                else:
                    attendance_summary['absent'] += 1
                
                attendance_summary['students'].append(student_data)
            
            # Calculate attendance percentage
            if len(enrollments) > 0:
                attended = attendance_summary['present'] + (attendance_summary['late'] * 0.5)
                attendance_summary['attendance_percentage'] = round((attended / len(enrollments)) * 100, 2)
            
            return {
                'success': True,
                'data': attendance_summary
            }
    
    def record_bulk_attendance(self, session_id: str, tutor_id: str, attendance_data: List[Dict]) -> Dict:
        """
        Record attendance for multiple students in a session
        
        Args:
            session_id: ID of the session
            tutor_id: ID of the tutor recording attendance
            attendance_data: List of attendance records
            
        Returns:
            Dict with success status and recorded attendance
        """
        with DatabaseContextManager() as ctx:
            # Verify session exists and tutor has permission
            session = ctx.session.query(TeachingSession).filter(
                TeachingSession.id == session_id,
                TeachingSession.tutor_id == tutor_id
            ).first()
            
            if not session:
                return {
                    'success': False,
                    'message': 'Session not found or tutor does not have permission'
                }
            
            if session.status not in ['ongoing', 'completed']:
                return {
                    'success': False,
                    'message': 'Attendance can only be recorded for ongoing or completed sessions'
                }
            
            recorded_attendance = []
            
            for student_data in attendance_data:
                student_id = student_data.get('student_id')
                status = student_data.get('status')
                notes = student_data.get('notes')
                late_minutes = student_data.get('late_minutes', 0)
                
                if not student_id or not status:
                    continue
                
                # Validate status
                try:
                    attendance_status = AttendanceStatus(status)
                except ValueError:
                    continue
                
                # Check if student is enrolled
                enrollment = ctx.session.query(Enrollment).filter(
                    Enrollment.course_id == session.course_id,
                    Enrollment.student_id == student_id,
                    Enrollment.status == 'active'
                ).first()
                
                if not enrollment:
                    continue
                
                # Check for existing attendance record
                existing_attendance = ctx.session.query(Attendance).filter(
                    Attendance.session_id == session_id,
                    Attendance.student_id == student_id
                ).first()
                
                if existing_attendance:
                    # Update existing record
                    existing_attendance.status = attendance_status
                    existing_attendance.timestamp = datetime.utcnow()
                    existing_attendance.notes = notes
                    existing_attendance.late_minutes = late_minutes
                    existing_attendance.updated_at = datetime.utcnow()
                    recorded_attendance.append(existing_attendance)
                else:
                    # Create new record
                    attendance = Attendance(
                        id=str(uuid.uuid4()),
                        session_id=session_id,
                        student_id=student_id,
                        tutor_id=tutor_id,
                        status=attendance_status,
                        timestamp=datetime.utcnow(),
                        notes=notes,
                        late_minutes=late_minutes,
                        verification_method='manual'
                    )
                    ctx.session.add(attendance)
                    recorded_attendance.append(attendance)
            
            try:
                ctx.session.commit()
                return {
                    'success': True,
                    'message': f'Recorded attendance for {len(recorded_attendance)} students',
                    'recorded_count': len(recorded_attendance)
                }
            except Exception as e:
                ctx.session.rollback()
                return {
                    'success': False,
                    'message': f'Failed to record attendance: {str(e)}'
                }


# Global instance
continuous_session_manager = ContinuousSessionManager()

