"""Analytics endpoints for HOD, Dean, and Senate dashboards."""

from typing import Optional
from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import func
from sqlalchemy.orm import Session

from app.api.deps import get_current_admin, get_current_user, get_db, require_user_type
from app.models.academic import (
    AcademicSession, AttendanceRecord, AttendanceStatus, Course, Enrollment,
    EnrollmentStatus, Programme
)
from app.models.finance import DeviceLoan, DeviceLoanStatus, LedgerEntryStatus, StudentLedger
from app.models.user import User, UserType
from app.schemas.common import SuccessResponse

router = APIRouter(prefix="/analytics", tags=["analytics"])


@router.get("/hod/overview", response_model=SuccessResponse)
async def get_hod_overview(
    department: Optional[str] = Query(None),
    db: Session = Depends(get_db),
    current_user = Depends(require_user_type(UserType.HEAD_OF_DEPARTMENT)),
):
    """Get HOD dashboard overview statistics for a department."""
    # If department not provided, try to get from user profile or use first available
    if not department:
        # Get first department from programmes (in production, link HOD user to department)
        first_dept = db.query(Programme.department).distinct().first()
        if first_dept:
            department = first_dept[0]
        else:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Department parameter required",
            )
    
    # Total students in department
    students_count = (
        db.query(func.count(func.distinct(Enrollment.student_id)))
        .join(Programme, Enrollment.programme_id == Programme.id)
        .filter(Programme.department == department)
        .filter(Enrollment.status == EnrollmentStatus.ACTIVE)
        .scalar() or 0
    )
    
    # Total courses in department
    courses_count = (
        db.query(func.count(Course.id))
        .join(Programme, Course.programme_id == Programme.id)
        .filter(Programme.department == department)
        .filter(Course.is_active == True)
        .scalar() or 0
    )
    
    # Attendance statistics
    attendance_records = (
        db.query(AttendanceRecord)
        .join(Enrollment, AttendanceRecord.enrollment_id == Enrollment.id)
        .join(Programme, Enrollment.programme_id == Programme.id)
        .filter(Programme.department == department)
        .all()
    )
    
    total_sessions = len(attendance_records)
    present_count = sum(1 for r in attendance_records if r.status == AttendanceStatus.PRESENT)
    attendance_rate = (present_count / total_sessions * 100) if total_sessions > 0 else 0
    
    # Risk students (low attendance)
    risk_students = (
        db.query(
            Enrollment.student_id,
            func.count(AttendanceRecord.id).filter(AttendanceRecord.status == AttendanceStatus.PRESENT).label('present'),
            func.count(AttendanceRecord.id).label('total')
        )
        .join(Programme, Enrollment.programme_id == Programme.id)
        .outerjoin(AttendanceRecord, AttendanceRecord.enrollment_id == Enrollment.id)
        .filter(Programme.department == department)
        .filter(Enrollment.status == EnrollmentStatus.ACTIVE)
        .group_by(Enrollment.student_id)
        .having(
            func.count(AttendanceRecord.id) > 0,
            func.count(AttendanceRecord.id).filter(AttendanceRecord.status == AttendanceStatus.PRESENT) * 100.0 / func.count(AttendanceRecord.id) < 75
        )
        .limit(10)
        .all()
    )
    
    risk_students_list = [
        {
            "student_id": str(s[0]),
            "attendance_rate": round((s[1] / s[2] * 100) if s[2] > 0 else 0, 2),
        }
        for s in risk_students
    ]
    
    # Recent enrollments
    recent_enrollments = (
        db.query(Enrollment)
        .join(Programme, Enrollment.programme_id == Programme.id)
        .filter(Programme.department == department)
        .order_by(Enrollment.enrollment_date.desc())
        .limit(5)
        .all()
    )
    
    return SuccessResponse(
        data={
            "department": department,
            "total_students": students_count,
            "total_courses": courses_count,
            "attendance_rate": round(attendance_rate, 2),
            "total_sessions": total_sessions,
            "present_sessions": present_count,
            "risk_students": risk_students_list,
            "recent_enrollments": [
                {
                    "student_id": str(e.student_id),
                    "course_id": str(e.course_id),
                    "enrollment_date": e.enrollment_date.isoformat() if e.enrollment_date else None,
                }
                for e in recent_enrollments
            ],
        },
        message="HOD overview statistics retrieved successfully",
    )


@router.get("/dean/overview", response_model=SuccessResponse)
async def get_dean_overview(
    faculty: Optional[str] = Query(None),
    db: Session = Depends(get_db),
    current_user = Depends(require_user_type(UserType.STUDENT_DEANERY)),
):
    """Get Dean dashboard overview statistics for a faculty."""
    # If faculty not provided, aggregate across all faculties
    base_query = db.query(Programme)
    if faculty:
        base_query = base_query.filter(Programme.faculty == faculty)
    
    # Total students in faculty
    students_query = (
        db.query(func.count(func.distinct(Enrollment.student_id)))
        .join(Programme, Enrollment.programme_id == Programme.id)
        .filter(Enrollment.status == EnrollmentStatus.ACTIVE)
    )
    if faculty:
        students_query = students_query.filter(Programme.faculty == faculty)
    
    students_count = students_query.scalar() or 0
    
    # Students by department
    dept_query = (
        db.query(
            Programme.department,
            func.count(func.distinct(Enrollment.student_id))
        )
        .join(Enrollment, Programme.id == Enrollment.programme_id)
        .filter(Enrollment.status == EnrollmentStatus.ACTIVE)
    )
    if faculty:
        dept_query = dept_query.filter(Programme.faculty == faculty)
    
    students_by_dept = {
        dept: count for dept, count in dept_query.group_by(Programme.department).all()
    }
    
    # Total programmes
    programmes_count = base_query.filter(Programme.is_active == True).count()
    
    # Total courses
    courses_query = (
        db.query(func.count(Course.id))
        .join(Programme, Course.programme_id == Programme.id)
        .filter(Course.is_active == True)
    )
    if faculty:
        courses_query = courses_query.filter(Programme.faculty == faculty)
    
    courses_count = courses_query.scalar() or 0
    
    # Overall attendance rate
    attendance_query = (
        db.query(AttendanceRecord)
        .join(Enrollment, AttendanceRecord.enrollment_id == Enrollment.id)
        .join(Programme, Enrollment.programme_id == Programme.id)
    )
    if faculty:
        attendance_query = attendance_query.filter(Programme.faculty == faculty)
    
    attendance_records = attendance_query.all()
    total_sessions = len(attendance_records)
    present_count = sum(1 for r in attendance_records if r.status == AttendanceStatus.PRESENT)
    attendance_rate = (present_count / total_sessions * 100) if total_sessions > 0 else 0
    
    return SuccessResponse(
        data={
            "faculty": faculty or "All Faculties",
            "total_students": students_count,
            "students_by_department": students_by_dept,
            "total_programmes": programmes_count,
            "total_courses": courses_count,
            "attendance_rate": round(attendance_rate, 2),
            "total_sessions": total_sessions,
            "present_sessions": present_count,
        },
        message="Dean overview statistics retrieved successfully",
    )


@router.get("/senate/overview", response_model=SuccessResponse)
async def get_senate_overview(
    db: Session = Depends(get_db),
    current_admin = Depends(get_current_admin),
):
    """Get Senate/Super Admin dashboard overview statistics (institution-wide KPIs)."""
    # Total students
    total_students = db.query(User).filter(User.user_type == UserType.GLOBAL_UNDERGRADUATE).count()
    
    # Total lecturers
    total_lecturers = db.query(User).filter(User.user_type == UserType.ACADEMIC_FACULTY).count()
    
    # Total programmes
    total_programmes = db.query(Programme).filter(Programme.is_active == True).count()
    
    # Total courses
    total_courses = db.query(Course).filter(Course.is_active == True).count()
    
    # Active enrollments
    active_enrollments = (
        db.query(Enrollment)
        .filter(Enrollment.status == EnrollmentStatus.ACTIVE)
        .count()
    )
    
    # Students by department
    students_by_dept = (
        db.query(
            Programme.department,
            func.count(func.distinct(Enrollment.student_id))
        )
        .join(Enrollment, Programme.id == Enrollment.programme_id)
        .filter(Enrollment.status == EnrollmentStatus.ACTIVE)
        .group_by(Programme.department)
        .all()
    )
    dept_stats = {dept: count for dept, count in students_by_dept}
    
    # Overall attendance rate
    attendance_records = db.query(AttendanceRecord).all()
    total_sessions = len(attendance_records)
    present_count = sum(1 for r in attendance_records if r.status == AttendanceStatus.PRESENT)
    attendance_rate = (present_count / total_sessions * 100) if total_sessions > 0 else 0
    
    # Financial statistics
    total_ledger_entries = db.query(StudentLedger).count()
    pending_payments = (
        db.query(func.sum(StudentLedger.amount))
        .filter(StudentLedger.status == LedgerEntryStatus.PENDING)
        .scalar() or 0
    )
    paid_payments = (
        db.query(func.sum(StudentLedger.amount))
        .filter(StudentLedger.status == LedgerEntryStatus.PAID)
        .scalar() or 0
    )
    
    # Device loans
    total_device_loans = db.query(DeviceLoan).count()
    active_device_loans = (
        db.query(DeviceLoan)
        .filter(DeviceLoan.status == DeviceLoanStatus.ACTIVE)
        .count()
    )
    
    # Current academic session
    current_session = db.query(AcademicSession).filter(AcademicSession.is_current == True).first()
    
    return SuccessResponse(
        data={
            "total_students": total_students,
            "total_lecturers": total_lecturers,
            "total_programmes": total_programmes,
            "total_courses": total_courses,
            "active_enrollments": active_enrollments,
            "students_by_department": dept_stats,
            "attendance_rate": round(attendance_rate, 2),
            "total_sessions": total_sessions,
            "present_sessions": present_count,
            "financial": {
                "total_ledger_entries": total_ledger_entries,
                "pending_payments": float(pending_payments),
                "paid_payments": float(paid_payments),
            },
            "device_loans": {
                "total": total_device_loans,
                "active": active_device_loans,
            },
            "current_session": current_session.name if current_session else None,
        },
        message="Senate overview statistics retrieved successfully",
    )
