from fastapi import APIRouter, Depends, File, Form, HTTPException, Query, UploadFile, status
from sqlalchemy.orm import Session, joinedload

from app.database import SessionLocal, get_db, release_db_connection
from app.dependencies import require_admin_token
from app.models import User
from app.models_admin import MemberSessionProgress
from app.schemas import (
    MarkMemberWeekCompleteRequest,
    MemberSessionProgressListResponse,
    MemberSessionProgressOut,
    MemberSessionProgressSaveRequest,
    MemberWeeksDetailResponse,
)
from app.services.admin_member_service import get_member_weeks_detail, mark_member_week_complete
from app.services.admin_service import (
    add_member_session_progress_images,
    calculate_member_points,
    list_member_session_progress,
    save_member_progress_image,
    save_member_session_progress,
    serialize_member_session_progress,
)

router = APIRouter(tags=["admin-member-progress"])


def _progress_response(db: Session, row):
    # Reload with relationships so image_urls includes all uploaded images.
    full = (
        db.query(MemberSessionProgress)
        .options(joinedload(MemberSessionProgress.assigned_by), joinedload(MemberSessionProgress.images))
        .filter(MemberSessionProgress.id == row.id)
        .first()
    )
    data = serialize_member_session_progress(full or row)
    points = calculate_member_points(db, row.user_id)
    data["assigned_points_total"] = points["assigned_points_total"]
    data["available_points"] = points["available_points"]
    return data


@router.post(
    "/save-member-session-progress",
    response_model=MemberSessionProgressOut,
    summary="Save assigned points, feedback, and completion for a member week/session",
)
def save_progress(
    body: MemberSessionProgressSaveRequest,
    db: Session = Depends(get_db),
    admin: User = Depends(require_admin_token),
):
    try:
        row = save_member_session_progress(db, admin, body)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) from e
    return _progress_response(db, row)


@router.post(
    "/save-member-session-progress-with-image",
    response_model=MemberSessionProgressOut,
    summary="Save member week/session progress with an optional image upload",
)
async def save_progress_with_image(
    user_id: int = Form(..., ge=1),
    week_id: int | None = Form(default=None, ge=1),
    week_name: str | None = Form(default=None),
    week_index: int | None = Form(default=None, ge=0),
    session_id: int | None = Form(default=None, ge=1),
    session_name: str | None = Form(default=None),
    session_number: int | None = Form(default=None, ge=1),
    assigned_points: int = Form(default=0, ge=0),
    feedback: str | None = Form(default=None),
    is_completed: bool = Form(default=False),
    image: UploadFile | None = File(default=None),
    images: list[UploadFile] | None = File(default=None),
    db: Session = Depends(get_db),
    admin: User = Depends(require_admin_token),
):
    body = MemberSessionProgressSaveRequest(
        user_id=user_id,
        week_id=week_id,
        week_name=week_name,
        week_index=week_index,
        session_id=session_id,
        session_name=session_name,
        session_number=session_number,
        assigned_points=assigned_points,
        feedback=feedback,
        is_completed=is_completed,
    )
    upload_files: list[UploadFile] = []
    if images:
        upload_files.extend([f for f in images if f and f.filename])
    if image and image.filename:
        upload_files.append(image)
    admin_id = admin.id
    release_db_connection(db)
    image_paths: list[str] = []
    for f in upload_files:
        image_paths.append(await save_member_progress_image(f))
    write_db = SessionLocal()
    try:
        admin_user = write_db.get(User, admin_id)
        if admin_user is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Admin not found")
        row = save_member_session_progress(
            write_db,
            admin_user,
            body,
            image_path=image_paths[0] if image_paths else None,
        )
        if len(image_paths) > 1:
            add_member_session_progress_images(
                write_db, progress_id=row.id, image_paths=image_paths[1:]
            )
        return _progress_response(write_db, row)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) from e
    finally:
        write_db.close()


@router.post(
    "/add-member-session-progress-images",
    response_model=MemberSessionProgressOut,
    summary="Append one or more images to an existing member_session_progress row",
)
async def add_progress_images(
    progress_id: int = Form(..., ge=1),
    images: list[UploadFile] | None = File(default=None),
    db: Session = Depends(get_db),
    _: User = Depends(require_admin_token),
):
    if not images:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Send at least one image file")
    release_db_connection(db)
    paths: list[str] = []
    for f in images:
        if f and f.filename:
            paths.append(await save_member_progress_image(f))
    if not paths:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Send at least one image file")
    write_db = SessionLocal()
    try:
        add_member_session_progress_images(write_db, progress_id=progress_id, image_paths=paths)
        row = write_db.get(MemberSessionProgress, progress_id)
        if not row:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Progress row not found")
        return _progress_response(write_db, row)
    finally:
        write_db.close()


@router.get(
    "/list-member-session-progress",
    response_model=MemberSessionProgressListResponse,
    summary="List saved points, feedback, and completion for one member",
)
def list_progress(
    user_id: int = Query(..., ge=1, description="Member user id"),
    db: Session = Depends(get_db),
    _: User = Depends(require_admin_token),
):
    rows = list_member_session_progress(db, user_id)
    return MemberSessionProgressListResponse(
        total=len(rows),
        progress=[serialize_member_session_progress(row) for row in rows],
    )


@router.get(
    "/member-weeks-detail",
    response_model=MemberWeeksDetailResponse,
    summary="Get member weeks and sessions with live progress for admin details page",
)
def member_weeks_detail(
    user_id: int = Query(..., ge=1, description="Member user id"),
    db: Session = Depends(get_db),
    _: User = Depends(require_admin_token),
):
    return get_member_weeks_detail(db, user_id)


@router.post(
    "/mark-member-week-complete",
    response_model=MemberWeeksDetailResponse,
    summary="Mark or unmark all sessions in a week as completed for a member",
)
def mark_week_complete(
    body: MarkMemberWeekCompleteRequest,
    db: Session = Depends(get_db),
    admin: User = Depends(require_admin_token),
):
    return mark_member_week_complete(db, body, admin)
