from typing import List, Optional
from datetime import datetime, date
from decimal import Decimal
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import func
from sqlalchemy.orm import Session
from .. import models, schemas
from ..database import get_db
from ..deps import get_current_admin
from ..security import hash_password

router = APIRouter()

# ── Dashboard stats ────────────────────────────────────────────────────────────

@router.get("/stats", response_model=schemas.AdminStats)
def get_stats(
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    total_users = db.query(func.count(models.User.id)).scalar()
    active_users = db.query(func.count(models.User.id)).filter(models.User.is_active == True).scalar()
    total_exams = db.query(func.count(models.Exam.id)).scalar()
    published_exams = db.query(func.count(models.Exam.id)).filter(models.Exam.is_published == True).scalar()
    total_sessions = db.query(func.count(models.ExamSession.id)).scalar()

    today_start = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
    sessions_today = db.query(func.count(models.ExamSession.id)).filter(
        models.ExamSession.started_at >= today_start
    ).scalar()

    finished = db.query(models.ExamSession).filter(models.ExamSession.status == "submitted").all()
    avg_grade = None
    pass_rate = None
    if finished:
        grades = [float(s.grade) for s in finished if s.grade is not None]
        if grades:
            avg_grade = round(sum(grades) / len(grades), 2)
            pass_rate = round(sum(1 for g in grades if g >= 5.0) / len(grades) * 100, 1)

    return schemas.AdminStats(
        total_users=total_users,
        active_users=active_users,
        total_exams=total_exams,
        published_exams=published_exams,
        total_sessions=total_sessions,
        sessions_today=sessions_today,
        average_grade=avg_grade,
        pass_rate=pass_rate,
    )


# ── User management ────────────────────────────────────────────────────────────

@router.get("/users", response_model=List[schemas.UserResponse])
def list_users(
    search: Optional[str] = None,
    is_active: Optional[bool] = None,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    q = db.query(models.User)
    if search:
        like = f"%{search}%"
        q = q.filter(
            models.User.email.ilike(like) |
            models.User.first_name.ilike(like) |
            models.User.last_name.ilike(like)
        )
    if is_active is not None:
        q = q.filter(models.User.is_active == is_active)
    return q.order_by(models.User.created_at.desc()).all()


@router.post("/users", response_model=schemas.UserResponse, status_code=201)
def create_user(
    body: schemas.UserAdminCreate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    if db.query(models.User).filter(models.User.email == body.email).first():
        raise HTTPException(status_code=400, detail="Email-ul este deja înregistrat")
    user = models.User(
        email=body.email,
        password_hash=hash_password(body.password),
        first_name=body.first_name,
        last_name=body.last_name,
        grade=body.grade,
        school=body.school,
        city=body.city,
        county=body.county,
        is_active=body.is_active,
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    return user


@router.get("/users/{user_id}", response_model=schemas.UserResponse)
def get_user(
    user_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    user = db.query(models.User).filter(models.User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="Utilizator negăsit")
    return user


@router.put("/users/{user_id}", response_model=schemas.UserResponse)
def update_user(
    user_id: str,
    body: schemas.UserUpdate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    user = db.query(models.User).filter(models.User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="Utilizator negăsit")

    payload = body.model_dump(exclude_none=True)

    # Handle email change with uniqueness check
    new_email = payload.pop("email", None)
    if new_email and new_email != user.email:
        if db.query(models.User).filter(models.User.email == new_email, models.User.id != user.id).first():
            raise HTTPException(status_code=400, detail="Email-ul este deja folosit de alt utilizator")
        user.email = new_email

    # Handle password change with hashing
    new_password = payload.pop("password", None)
    if new_password:
        user.password_hash = hash_password(new_password)

    for field, value in payload.items():
        setattr(user, field, value)
    db.commit()
    db.refresh(user)
    return user


@router.delete("/users/{user_id}", status_code=204)
def delete_user(
    user_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    user = db.query(models.User).filter(models.User.id == user_id).first()
    if not user:
        raise HTTPException(status_code=404, detail="Utilizator negăsit")
    db.delete(user)
    db.commit()


@router.get("/users/{user_id}/sessions")
def user_sessions(
    user_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    sessions = (
        db.query(models.ExamSession)
        .filter(models.ExamSession.user_id == user_id)
        .order_by(models.ExamSession.started_at.desc())
        .all()
    )
    return [
        {
            "id": str(s.id),
            "exam_title": s.exam.title,
            "subject": s.exam.subject.name,
            "exam_type": s.exam.exam_type.code,
            "started_at": s.started_at.isoformat(),
            "submitted_at": s.submitted_at.isoformat() if s.submitted_at else None,
            "status": s.status,
            "grade": float(s.grade) if s.grade else None,
            "passed": s.passed,
        }
        for s in sessions
    ]


# ── Exam management ────────────────────────────────────────────────────────────

@router.get("/exams", response_model=List[schemas.ExamSummary])
def list_exams(
    exam_type_id: Optional[int] = None,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    q = db.query(models.Exam)
    if exam_type_id:
        q = q.filter(models.Exam.exam_type_id == exam_type_id)
    exams = q.order_by(models.Exam.created_at.desc()).all()
    result = []
    for e in exams:
        result.append(schemas.ExamSummary(
            id=e.id,
            title=e.title,
            subject=schemas.SubjectResponse.model_validate(e.subject),
            exam_type=schemas.ExamTypeResponse.model_validate(e.exam_type),
            year=e.year,
            duration_minutes=e.duration_minutes,
            total_points=e.total_points,
            question_count=len(e.questions),
            is_published=e.is_published,
        ))
    return result


@router.post("/exams", response_model=schemas.ExamSummary, status_code=201)
def create_exam(
    body: schemas.ExamCreate,
    db: Session = Depends(get_db),
    admin: models.Administrator = Depends(get_current_admin),
):
    subject = db.query(models.Subject).filter(models.Subject.id == body.subject_id).first()
    exam_type = db.query(models.ExamType).filter(models.ExamType.id == body.exam_type_id).first()
    if not subject or not exam_type:
        raise HTTPException(status_code=400, detail="Materie sau tip de examen invalid")

    exam = models.Exam(
        title=body.title,
        subject_id=body.subject_id,
        exam_type_id=body.exam_type_id,
        year=body.year,
        duration_minutes=body.duration_minutes,
        total_points=body.total_points,
        instructions=body.instructions,
        created_by=admin.id,
    )
    db.add(exam)
    db.commit()
    db.refresh(exam)
    return schemas.ExamSummary(
        id=exam.id,
        title=exam.title,
        subject=schemas.SubjectResponse.model_validate(exam.subject),
        exam_type=schemas.ExamTypeResponse.model_validate(exam.exam_type),
        year=exam.year,
        duration_minutes=exam.duration_minutes,
        total_points=exam.total_points,
        question_count=0,
        is_published=exam.is_published,
    )


@router.get("/exams/{exam_id}", response_model=schemas.ExamAdminDetail)
def get_exam_admin(
    exam_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    exam = db.query(models.Exam).filter(models.Exam.id == exam_id).first()
    if not exam:
        raise HTTPException(status_code=404, detail="Examen negăsit")
    return _build_admin_detail(exam)


@router.put("/exams/{exam_id}", response_model=schemas.ExamSummary)
def update_exam(
    exam_id: str,
    body: schemas.ExamUpdate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    exam = db.query(models.Exam).filter(models.Exam.id == exam_id).first()
    if not exam:
        raise HTTPException(status_code=404, detail="Examen negăsit")
    for field, value in body.model_dump(exclude_none=True).items():
        setattr(exam, field, value)
    db.commit()
    db.refresh(exam)
    return schemas.ExamSummary(
        id=exam.id,
        title=exam.title,
        subject=schemas.SubjectResponse.model_validate(exam.subject),
        exam_type=schemas.ExamTypeResponse.model_validate(exam.exam_type),
        year=exam.year,
        duration_minutes=exam.duration_minutes,
        total_points=exam.total_points,
        question_count=len(exam.questions),
        is_published=exam.is_published,
    )


@router.post("/exams/{exam_id}/publish")
def toggle_publish(
    exam_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    exam = db.query(models.Exam).filter(models.Exam.id == exam_id).first()
    if not exam:
        raise HTTPException(status_code=404, detail="Examen negăsit")
    exam.is_published = not exam.is_published
    db.commit()
    return {"is_published": exam.is_published}


@router.delete("/exams/{exam_id}", status_code=204)
def delete_exam(
    exam_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    exam = db.query(models.Exam).filter(models.Exam.id == exam_id).first()
    if not exam:
        raise HTTPException(status_code=404, detail="Examen negăsit")
    db.delete(exam)
    db.commit()


# ── Question management ────────────────────────────────────────────────────────

@router.post("/exams/{exam_id}/questions", response_model=schemas.QuestionAdminResponse, status_code=201)
def add_question(
    exam_id: str,
    body: schemas.QuestionCreate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    exam = db.query(models.Exam).filter(models.Exam.id == exam_id).first()
    if not exam:
        raise HTTPException(status_code=404, detail="Examen negăsit")

    question_count = len(exam.questions)
    question = models.Question(
        exam_id=exam_id,
        question_number=question_count + 1,
        question_type=body.question_type,
        question_text=body.question_text,
        points=body.points,
        order_index=body.order_index,
    )
    db.add(question)
    db.flush()

    for opt in body.options:
        db.add(models.QuestionOption(
            question_id=question.id,
            option_label=opt.option_label,
            option_text=opt.option_text,
            is_correct=opt.is_correct,
        ))

    db.commit()
    db.refresh(question)
    return _build_question_admin(question)


@router.put("/questions/{question_id}", response_model=schemas.QuestionAdminResponse)
def update_question(
    question_id: str,
    body: schemas.QuestionUpdate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    question = db.query(models.Question).filter(models.Question.id == question_id).first()
    if not question:
        raise HTTPException(status_code=404, detail="Întrebare negăsită")
    for field, value in body.model_dump(exclude_none=True).items():
        setattr(question, field, value)
    db.commit()
    db.refresh(question)
    return _build_question_admin(question)


@router.delete("/questions/{question_id}", status_code=204)
def delete_question(
    question_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    question = db.query(models.Question).filter(models.Question.id == question_id).first()
    if not question:
        raise HTTPException(status_code=404, detail="Întrebare negăsită")
    db.delete(question)
    db.commit()


@router.post("/questions/{question_id}/options", status_code=201)
def add_option(
    question_id: str,
    body: schemas.OptionCreate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    question = db.query(models.Question).filter(models.Question.id == question_id).first()
    if not question:
        raise HTTPException(status_code=404, detail="Întrebare negăsită")
    option = models.QuestionOption(
        question_id=question_id,
        option_label=body.option_label,
        option_text=body.option_text,
        is_correct=body.is_correct,
    )
    db.add(option)
    db.commit()
    db.refresh(option)
    return {"id": str(option.id), **body.model_dump()}


@router.put("/options/{option_id}")
def update_option(
    option_id: str,
    body: schemas.OptionUpdate,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    option = db.query(models.QuestionOption).filter(models.QuestionOption.id == option_id).first()
    if not option:
        raise HTTPException(status_code=404, detail="Opțiune negăsită")
    for field, value in body.model_dump(exclude_none=True).items():
        setattr(option, field, value)
    db.commit()
    return {"ok": True}


@router.delete("/options/{option_id}", status_code=204)
def delete_option(
    option_id: str,
    db: Session = Depends(get_db),
    _: models.Administrator = Depends(get_current_admin),
):
    option = db.query(models.QuestionOption).filter(models.QuestionOption.id == option_id).first()
    if not option:
        raise HTTPException(status_code=404, detail="Opțiune negăsită")
    db.delete(option)
    db.commit()


# ── Admin management ───────────────────────────────────────────────────────────

@router.post("/admins", response_model=schemas.AdminResponse, status_code=201)
def create_admin(
    body: schemas.AdminCreate,
    db: Session = Depends(get_db),
    current: models.Administrator = Depends(get_current_admin),
):
    if current.role != "superadmin":
        raise HTTPException(status_code=403, detail="Doar superadmin poate crea conturi de admin")
    if db.query(models.Administrator).filter(models.Administrator.email == body.email).first():
        raise HTTPException(status_code=400, detail="Email-ul există deja")
    admin = models.Administrator(
        email=body.email,
        password_hash=hash_password(body.password),
        first_name=body.first_name,
        last_name=body.last_name,
        role=body.role,
    )
    db.add(admin)
    db.commit()
    db.refresh(admin)
    return admin


# ── helpers ────────────────────────────────────────────────────────────────────

def _build_question_admin(q: models.Question) -> schemas.QuestionAdminResponse:
    options = [
        schemas.OptionWithCorrect(
            id=o.id, option_label=o.option_label,
            option_text=o.option_text, is_correct=o.is_correct,
        )
        for o in q.options
    ]
    return schemas.QuestionAdminResponse(
        id=q.id,
        question_number=q.question_number,
        question_type=q.question_type,
        question_text=q.question_text,
        points=q.points,
        order_index=q.order_index,
        options=options,
    )


def _build_admin_detail(exam: models.Exam) -> schemas.ExamAdminDetail:
    questions = [_build_question_admin(q) for q in exam.questions]
    return schemas.ExamAdminDetail(
        id=exam.id,
        title=exam.title,
        subject=schemas.SubjectResponse.model_validate(exam.subject),
        exam_type=schemas.ExamTypeResponse.model_validate(exam.exam_type),
        year=exam.year,
        duration_minutes=exam.duration_minutes,
        total_points=exam.total_points,
        instructions=exam.instructions,
        is_published=exam.is_published,
        created_at=exam.created_at,
        questions=questions,
    )
