from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.auth.demo_auth import get_admin_user, get_current_user
from app.database import get_db
from app.models.content_tracking import ContentAccessLog, Quiz, QuizAttempt, TrackedLink
from app.models.user import User
from app.services.content_tracker import generate_short_code, log_content_access, score_quiz_attempt

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


# --- Tracked Link Redirect (public, no auth) ---

@router.get("/r/{short_code}")
async def redirect_tracked_link(
    short_code: str,
    uid: str | None = None,
    request: Request = None,
    db: AsyncSession = Depends(get_db),
):
    """Public redirect endpoint. Logs access and redirects to destination."""
    link = await log_content_access(
        db,
        short_code=short_code,
        user_email=uid,
        user_agent=request.headers.get("user-agent") if request else None,
        ip_address=request.client.host if request and request.client else None,
    )
    if not link:
        raise HTTPException(status_code=404, detail="Link not found")
    return RedirectResponse(url=link.destination_url, status_code=302)


# --- Tracked Links CRUD (admin) ---

class CreateTrackedLinkRequest(BaseModel):
    activity_id: str | None = None
    destination_url: str
    title: str | None = None
    content_type: str | None = None
    shared_in_channel: str | None = None


@router.post("/content/tracked-links")
async def create_tracked_link(
    req: CreateTrackedLinkRequest,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    from datetime import datetime, timezone
    link = TrackedLink(
        activity_id=UUID(req.activity_id) if req.activity_id else None,
        short_code=generate_short_code(),
        destination_url=req.destination_url,
        title=req.title,
        content_type=req.content_type,
        shared_in_channel=req.shared_in_channel,
        shared_by=admin.id,
        shared_at=datetime.now(timezone.utc),
    )
    db.add(link)
    await db.flush()

    from app.config import get_settings
    base = get_settings().base_url
    return {
        "id": str(link.id),
        "short_code": link.short_code,
        "redirect_url": f"{base}/r/{link.short_code}",
        "destination_url": link.destination_url,
        "title": link.title,
        "content_type": link.content_type,
        "click_count": 0,
        "created_at": link.created_at.isoformat(),
    }


@router.get("/content/tracked-links")
async def list_tracked_links(db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
    result = await db.execute(select(TrackedLink).order_by(TrackedLink.created_at.desc()))
    links = result.scalars().all()
    from app.config import get_settings
    base = get_settings().base_url
    return [
        {
            "id": str(l.id),
            "short_code": l.short_code,
            "redirect_url": f"{base}/r/{l.short_code}",
            "destination_url": l.destination_url,
            "title": l.title,
            "content_type": l.content_type,
            "click_count": l.click_count,
            "shared_in_channel": l.shared_in_channel,
            "created_at": l.created_at.isoformat(),
        }
        for l in links
    ]


@router.get("/content/tracked-links/{link_id}/access")
async def get_access_logs(link_id: str, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
    result = await db.execute(
        select(ContentAccessLog)
        .where(ContentAccessLog.tracked_link_id == UUID(link_id))
        .order_by(ContentAccessLog.accessed_at.desc())
    )
    logs = result.scalars().all()
    items = []
    for log in logs:
        user = await db.get(User, log.user_id) if log.user_id else None
        items.append({
            "id": str(log.id),
            "user": {"id": str(user.id), "full_name": user.full_name, "email": user.email} if user else None,
            "user_email": log.user_email,
            "accessed_at": log.accessed_at.isoformat(),
        })
    return items


# --- Quizzes ---

class CreateQuizRequest(BaseModel):
    activity_id: str | None = None
    title: str
    description: str | None = None
    passing_score_pct: int = 70
    questions: list[dict]
    time_limit_minutes: int | None = None


class SubmitQuizRequest(BaseModel):
    answers: list[int]


@router.post("/content/quizzes")
async def create_quiz(
    req: CreateQuizRequest,
    db: AsyncSession = Depends(get_db),
    admin: User = Depends(get_admin_user),
):
    quiz = Quiz(
        activity_id=UUID(req.activity_id) if req.activity_id else None,
        title=req.title,
        description=req.description,
        passing_score_pct=req.passing_score_pct,
        questions=req.questions,
        time_limit_minutes=req.time_limit_minutes,
        created_by=admin.id,
    )
    db.add(quiz)
    await db.flush()
    return {"id": str(quiz.id), "title": quiz.title, "question_count": len(req.questions)}


@router.get("/content/quizzes/{quiz_id}")
async def get_quiz(quiz_id: str, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
    quiz = await db.get(Quiz, UUID(quiz_id))
    if not quiz:
        raise HTTPException(status_code=404)
    # Strip correct answers for non-admin
    questions = []
    raw = quiz.questions if isinstance(quiz.questions, list) else quiz.questions.get("questions", [])
    for q in raw:
        questions.append({
            "question": q["question"],
            "options": q["options"],
        })
    return {
        "id": str(quiz.id),
        "title": quiz.title,
        "description": quiz.description,
        "passing_score_pct": quiz.passing_score_pct,
        "questions": questions,
        "time_limit_minutes": quiz.time_limit_minutes,
    }


@router.post("/content/quizzes/{quiz_id}/submit")
async def submit_quiz(
    quiz_id: str,
    req: SubmitQuizRequest,
    db: AsyncSession = Depends(get_db),
    user: User = Depends(get_current_user),
):
    attempt = await score_quiz_attempt(db, UUID(quiz_id), user.id, req.answers)
    return {
        "id": str(attempt.id),
        "score_pct": attempt.score_pct,
        "passed": attempt.passed,
        "xp_awarded": attempt.xp_awarded,
    }


@router.get("/content/quizzes/{quiz_id}/results")
async def get_quiz_results(
    quiz_id: str,
    db: AsyncSession = Depends(get_db),
    _=Depends(get_admin_user),
):
    result = await db.execute(
        select(QuizAttempt)
        .where(QuizAttempt.quiz_id == UUID(quiz_id))
        .order_by(QuizAttempt.completed_at.desc())
    )
    attempts = result.scalars().all()
    items = []
    for a in attempts:
        user = await db.get(User, a.user_id)
        items.append({
            "id": str(a.id),
            "user": {"id": str(user.id), "full_name": user.full_name} if user else None,
            "score_pct": a.score_pct,
            "passed": a.passed,
            "xp_awarded": a.xp_awarded,
            "completed_at": a.completed_at.isoformat(),
        })
    return items
