"""
用户课程学习进度 API
"""
from datetime import datetime
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, and_
from pydantic import BaseModel, Field

from app.core.deps import get_db, get_current_user
from app.models.user import User
from app.models.course import Course, CourseMaterial
from app.models.user_course_progress import (
    UserCourseProgress,
    UserMaterialProgress,
    ProgressStatus,
)

router = APIRouter()


# ============ Schemas ============

class MaterialProgressUpdate(BaseModel):
    """更新资料进度请求"""
    progress_percent: float = Field(ge=0, le=100, description="进度百分比")
    last_position: Optional[int] = Field(default=0, ge=0, description="播放位置(秒)")
    study_time_delta: Optional[int] = Field(default=0, ge=0, description="本次学习时长(秒)")
    is_completed: Optional[bool] = Field(default=None, description="是否标记完成")


class MaterialProgressResponse(BaseModel):
    """资料进度响应"""
    material_id: int
    material_name: str
    is_completed: bool
    progress_percent: float
    last_position: int
    study_time: int
    first_accessed_at: Optional[datetime]
    last_accessed_at: Optional[datetime]
    completed_at: Optional[datetime]

    class Config:
        from_attributes = True


class CourseProgressResponse(BaseModel):
    """课程进度响应"""
    course_id: int
    course_name: str
    status: str
    progress_percent: float
    completed_materials: int
    total_materials: int
    total_study_time: int
    first_accessed_at: Optional[datetime]
    last_accessed_at: Optional[datetime]
    completed_at: Optional[datetime]
    materials: List[MaterialProgressResponse] = []

    class Config:
        from_attributes = True


class ProgressSummary(BaseModel):
    """进度统计摘要"""
    total_courses: int
    completed_courses: int
    in_progress_courses: int
    not_started_courses: int
    total_study_time: int
    average_progress: float


# ============ API Endpoints ============

@router.get("/summary", response_model=ProgressSummary)
async def get_progress_summary(
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """获取用户学习进度摘要"""
    # 获取用户所有课程进度
    result = await db.execute(
        select(UserCourseProgress).where(
            UserCourseProgress.user_id == current_user.id
        )
    )
    progress_list = result.scalars().all()
    
    total_courses = len(progress_list)
    completed = sum(1 for p in progress_list if p.status == ProgressStatus.COMPLETED.value)
    in_progress = sum(1 for p in progress_list if p.status == ProgressStatus.IN_PROGRESS.value)
    not_started = sum(1 for p in progress_list if p.status == ProgressStatus.NOT_STARTED.value)
    total_time = sum(p.total_study_time for p in progress_list)
    avg_progress = sum(p.progress_percent for p in progress_list) / total_courses if total_courses > 0 else 0
    
    return ProgressSummary(
        total_courses=total_courses,
        completed_courses=completed,
        in_progress_courses=in_progress,
        not_started_courses=not_started,
        total_study_time=total_time,
        average_progress=round(avg_progress, 2),
    )


@router.get("/courses", response_model=List[CourseProgressResponse])
async def get_all_course_progress(
    status: Optional[str] = Query(None, description="过滤状态"),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """获取用户所有课程的学习进度"""
    query = select(UserCourseProgress, Course).join(
        Course, UserCourseProgress.course_id == Course.id
    ).where(
        UserCourseProgress.user_id == current_user.id
    )
    
    if status:
        query = query.where(UserCourseProgress.status == status)
    
    result = await db.execute(query)
    rows = result.all()
    
    response = []
    for progress, course in rows:
        response.append(CourseProgressResponse(
            course_id=course.id,
            course_name=course.name,
            status=progress.status,
            progress_percent=progress.progress_percent,
            completed_materials=progress.completed_materials,
            total_materials=progress.total_materials,
            total_study_time=progress.total_study_time,
            first_accessed_at=progress.first_accessed_at,
            last_accessed_at=progress.last_accessed_at,
            completed_at=progress.completed_at,
        ))
    
    return response


@router.get("/courses/{course_id}", response_model=CourseProgressResponse)
async def get_course_progress(
    course_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """获取指定课程的详细学习进度"""
    # 获取课程信息
    course_result = await db.execute(
        select(Course).where(Course.id == course_id)
    )
    course = course_result.scalar_one_or_none()
    if not course:
        raise HTTPException(status_code=404, detail="课程不存在")
    
    # 获取或创建课程进度
    progress_result = await db.execute(
        select(UserCourseProgress).where(
            and_(
                UserCourseProgress.user_id == current_user.id,
                UserCourseProgress.course_id == course_id,
            )
        )
    )
    progress = progress_result.scalar_one_or_none()
    
    if not progress:
        # 获取课程资料数量
        materials_result = await db.execute(
            select(func.count(CourseMaterial.id)).where(
                and_(
                    CourseMaterial.course_id == course_id,
                    CourseMaterial.is_deleted == False,
                )
            )
        )
        total_materials = materials_result.scalar() or 0
        
        # 创建新的进度记录
        progress = UserCourseProgress(
            user_id=current_user.id,
            course_id=course_id,
            status=ProgressStatus.NOT_STARTED.value,
            progress_percent=0.0,
            completed_materials=0,
            total_materials=total_materials,
        )
        db.add(progress)
        await db.commit()
        await db.refresh(progress)
    
    # 获取资料进度
    material_progress_result = await db.execute(
        select(UserMaterialProgress, CourseMaterial).join(
            CourseMaterial, UserMaterialProgress.material_id == CourseMaterial.id
        ).where(
            and_(
                UserMaterialProgress.user_id == current_user.id,
                UserMaterialProgress.course_id == course_id,
            )
        )
    )
    material_rows = material_progress_result.all()
    
    materials = []
    for mp, material in material_rows:
        materials.append(MaterialProgressResponse(
            material_id=material.id,
            material_name=material.name,
            is_completed=mp.is_completed,
            progress_percent=mp.progress_percent,
            last_position=mp.last_position,
            study_time=mp.study_time,
            first_accessed_at=mp.first_accessed_at,
            last_accessed_at=mp.last_accessed_at,
            completed_at=mp.completed_at,
        ))
    
    return CourseProgressResponse(
        course_id=course.id,
        course_name=course.name,
        status=progress.status,
        progress_percent=progress.progress_percent,
        completed_materials=progress.completed_materials,
        total_materials=progress.total_materials,
        total_study_time=progress.total_study_time,
        first_accessed_at=progress.first_accessed_at,
        last_accessed_at=progress.last_accessed_at,
        completed_at=progress.completed_at,
        materials=materials,
    )


@router.post("/materials/{material_id}", response_model=MaterialProgressResponse)
async def update_material_progress(
    material_id: int,
    data: MaterialProgressUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """更新资料学习进度"""
    # 获取资料信息
    material_result = await db.execute(
        select(CourseMaterial).where(CourseMaterial.id == material_id)
    )
    material = material_result.scalar_one_or_none()
    if not material:
        raise HTTPException(status_code=404, detail="资料不存在")
    
    course_id = material.course_id
    now = datetime.now()
    
    # 获取或创建资料进度
    mp_result = await db.execute(
        select(UserMaterialProgress).where(
            and_(
                UserMaterialProgress.user_id == current_user.id,
                UserMaterialProgress.material_id == material_id,
            )
        )
    )
    mp = mp_result.scalar_one_or_none()
    
    if not mp:
        mp = UserMaterialProgress(
            user_id=current_user.id,
            material_id=material_id,
            course_id=course_id,
            first_accessed_at=now,
        )
        db.add(mp)
    
    # 更新进度
    mp.progress_percent = data.progress_percent
    mp.last_position = data.last_position or mp.last_position
    mp.study_time += data.study_time_delta or 0
    mp.last_accessed_at = now
    
    # 处理完成状态
    if data.is_completed is not None:
        if data.is_completed and not mp.is_completed:
            mp.is_completed = True
            mp.completed_at = now
            mp.progress_percent = 100.0
        elif not data.is_completed:
            mp.is_completed = False
            mp.completed_at = None
    elif data.progress_percent >= 100:
        mp.is_completed = True
        mp.completed_at = now
    
    await db.commit()
    
    # 更新课程整体进度
    await _update_course_progress(db, current_user.id, course_id)
    
    await db.refresh(mp)
    
    return MaterialProgressResponse(
        material_id=mp.material_id,
        material_name=material.name,
        is_completed=mp.is_completed,
        progress_percent=mp.progress_percent,
        last_position=mp.last_position,
        study_time=mp.study_time,
        first_accessed_at=mp.first_accessed_at,
        last_accessed_at=mp.last_accessed_at,
        completed_at=mp.completed_at,
    )


@router.post("/materials/{material_id}/complete")
async def mark_material_complete(
    material_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """标记资料为已完成"""
    return await update_material_progress(
        material_id=material_id,
        data=MaterialProgressUpdate(progress_percent=100, is_completed=True),
        db=db,
        current_user=current_user,
    )


@router.post("/courses/{course_id}/start")
async def start_course(
    course_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    """开始学习课程（记录首次访问）"""
    # 获取课程
    course_result = await db.execute(
        select(Course).where(Course.id == course_id)
    )
    course = course_result.scalar_one_or_none()
    if not course:
        raise HTTPException(status_code=404, detail="课程不存在")
    
    now = datetime.now()
    
    # 获取或创建进度
    progress_result = await db.execute(
        select(UserCourseProgress).where(
            and_(
                UserCourseProgress.user_id == current_user.id,
                UserCourseProgress.course_id == course_id,
            )
        )
    )
    progress = progress_result.scalar_one_or_none()
    
    if not progress:
        # 获取资料数量
        materials_result = await db.execute(
            select(func.count(CourseMaterial.id)).where(
                and_(
                    CourseMaterial.course_id == course_id,
                    CourseMaterial.is_deleted == False,
                )
            )
        )
        total_materials = materials_result.scalar() or 0
        
        progress = UserCourseProgress(
            user_id=current_user.id,
            course_id=course_id,
            status=ProgressStatus.IN_PROGRESS.value,
            total_materials=total_materials,
            first_accessed_at=now,
            last_accessed_at=now,
        )
        db.add(progress)
    else:
        if progress.status == ProgressStatus.NOT_STARTED.value:
            progress.status = ProgressStatus.IN_PROGRESS.value
        if not progress.first_accessed_at:
            progress.first_accessed_at = now
        progress.last_accessed_at = now
    
    await db.commit()
    
    return {"code": 200, "message": "已开始学习", "data": {"course_id": course_id}}


# ============ Helper Functions ============

async def _update_course_progress(db: AsyncSession, user_id: int, course_id: int):
    """更新课程整体进度"""
    now = datetime.now()
    
    # 获取课程所有资料数量
    materials_result = await db.execute(
        select(func.count(CourseMaterial.id)).where(
            and_(
                CourseMaterial.course_id == course_id,
                CourseMaterial.is_deleted == False,
            )
        )
    )
    total_materials = materials_result.scalar() or 0
    
    # 获取已完成的资料数量和总学习时长
    completed_result = await db.execute(
        select(
            func.count(UserMaterialProgress.id),
            func.coalesce(func.sum(UserMaterialProgress.study_time), 0),
        ).where(
            and_(
                UserMaterialProgress.user_id == user_id,
                UserMaterialProgress.course_id == course_id,
                UserMaterialProgress.is_completed == True,
            )
        )
    )
    row = completed_result.one()
    completed_materials = row[0]
    total_study_time = row[1]
    
    # 计算进度百分比
    progress_percent = (completed_materials / total_materials * 100) if total_materials > 0 else 0
    
    # 确定状态
    if completed_materials == 0:
        status = ProgressStatus.IN_PROGRESS.value  # 已开始但未完成任何资料
    elif completed_materials >= total_materials:
        status = ProgressStatus.COMPLETED.value
    else:
        status = ProgressStatus.IN_PROGRESS.value
    
    # 获取或创建课程进度
    progress_result = await db.execute(
        select(UserCourseProgress).where(
            and_(
                UserCourseProgress.user_id == user_id,
                UserCourseProgress.course_id == course_id,
            )
        )
    )
    progress = progress_result.scalar_one_or_none()
    
    if not progress:
        progress = UserCourseProgress(
            user_id=user_id,
            course_id=course_id,
            first_accessed_at=now,
        )
        db.add(progress)
    
    # 更新进度
    progress.status = status
    progress.progress_percent = round(progress_percent, 2)
    progress.completed_materials = completed_materials
    progress.total_materials = total_materials
    progress.total_study_time = total_study_time
    progress.last_accessed_at = now
    
    if status == ProgressStatus.COMPLETED.value and not progress.completed_at:
        progress.completed_at = now
    
    await db.commit()
