from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.api.deps import get_current_active_user
from app.models import User, Session, SessionRating
from app.models.step_library import StepLibrary, StepRating
from app.schemas.analytics import SessionRatingCreate, SessionRatingResponse, StepFeedbackCreate

router = APIRouter(tags=["ratings"])


@router.post("/sessions/{session_id}/rate", response_model=SessionRatingResponse, status_code=status.HTTP_201_CREATED)
async def rate_session(
    session_id: UUID,
    data: SessionRatingCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """Submit a CSAT rating (1-5) for a completed session."""
    # Verify session exists and belongs to user
    result = await db.execute(select(Session).where(Session.id == session_id))
    session = result.scalar_one_or_none()
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")
    if session.user_id != current_user.id:
        raise HTTPException(status_code=403, detail="Not your session")
    if not session.completed_at:
        raise HTTPException(status_code=400, detail="Session not completed yet")

    # Check for duplicate
    existing = await db.execute(
        select(SessionRating).where(SessionRating.session_id == session_id)
    )
    if existing.scalar_one_or_none():
        raise HTTPException(status_code=409, detail="Session already rated")

    rating = SessionRating(
        session_id=session_id,
        user_id=current_user.id,
        tree_id=session.tree_id,
        account_id=current_user.account_id,
        rating=data.rating,
        comment=data.comment,
    )
    db.add(rating)
    await db.commit()
    await db.refresh(rating)

    return SessionRatingResponse(
        id=str(rating.id),
        session_id=str(rating.session_id),
        rating=rating.rating,
        comment=rating.comment,
        created_at=rating.created_at,
    )


@router.post("/steps/{step_id}/feedback", status_code=status.HTTP_201_CREATED)
async def submit_step_feedback(
    step_id: UUID,
    data: StepFeedbackCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """Submit thumbs up/down feedback for a step used in a session."""
    # Verify step exists
    result = await db.execute(select(StepLibrary).where(StepLibrary.id == step_id))
    step = result.scalar_one_or_none()
    if not step:
        raise HTTPException(status_code=404, detail="Step not found")

    session_uuid = UUID(data.session_id)

    # Check for existing feedback for this step+user+session
    existing_result = await db.execute(
        select(StepRating).where(
            StepRating.step_id == step_id,
            StepRating.user_id == current_user.id,
            StepRating.session_id == session_uuid,
        )
    )
    existing = existing_result.scalar_one_or_none()

    if existing:
        existing.was_helpful = data.was_helpful
        resp_status = "updated"
    else:
        new_rating = StepRating(
            step_id=step_id,
            user_id=current_user.id,
            session_id=session_uuid,
            was_helpful=data.was_helpful,
            # rating is nullable now — thumbs-only mode
        )
        db.add(new_rating)
        resp_status = "created"

    # Update aggregates on step_library
    await _update_step_helpful_counts(db, step_id)
    await db.commit()

    return {"step_id": str(step_id), "was_helpful": data.was_helpful, "status": resp_status}


async def _update_step_helpful_counts(db: AsyncSession, step_id: UUID):
    """Recalculate helpful_yes and helpful_no on step_library."""
    yes_q = await db.execute(
        select(func.count()).select_from(StepRating).where(
            StepRating.step_id == step_id, StepRating.was_helpful == True
        )
    )
    no_q = await db.execute(
        select(func.count()).select_from(StepRating).where(
            StepRating.step_id == step_id, StepRating.was_helpful == False
        )
    )
    await db.execute(
        StepLibrary.__table__.update()
        .where(StepLibrary.id == step_id)
        .values(helpful_yes=yes_q.scalar() or 0, helpful_no=no_q.scalar() or 0)
    )
