from sqlalchemy.orm import Session, joinedload

from app.core.config import settings
from app.models.user import ExamRecord, Subject, SubjectScore
from app.schemas import ExamTypeEnum, TrendPoint, TrendResponse


def build_trend(db: Session, student_id, subject_id: int) -> TrendResponse:
    subject = db.get(Subject, subject_id)
    if subject is None:
        raise ValueError("科目不存在")

    scores = (
        db.query(SubjectScore)
        .join(ExamRecord)
        .options(joinedload(SubjectScore.exam_record))
        .filter(
            ExamRecord.student_id == student_id,
            SubjectScore.subject_id == subject_id,
        )
        .order_by(ExamRecord.exam_date.asc(), ExamRecord.created_at.asc())
        .all()
    )

    threshold = settings.FLUCTUATION_THRESHOLD
    points: list[TrendPoint] = []
    prev_ratio: float | None = None

    for score in scores:
        exam = score.exam_record
        ratio = float(score.ratio)
        delta = None if prev_ratio is None else ratio - prev_ratio
        direction = None
        is_volatile = False

        if delta is not None:
            if delta > 0:
                direction = "up"
            elif delta < 0:
                direction = "down"
            else:
                direction = "flat"
            is_volatile = abs(delta) >= threshold

        points.append(
            TrendPoint(
                exam_id=exam.id,
                exam_type=ExamTypeEnum(exam.exam_type.value),
                exam_date=exam.exam_date,
                title=exam.title,
                ratio=ratio,
                ratio_percent=round(ratio * 100, 2),
                delta=delta,
                delta_percent=round(delta * 100, 2) if delta is not None else None,
                is_volatile=is_volatile,
                direction=direction,
            )
        )
        prev_ratio = ratio

    return TrendResponse(
        subject_id=subject_id,
        subject_name=subject.name,
        threshold=threshold,
        points=points,
    )
