from __future__ import annotations

import csv
from datetime import datetime
from io import StringIO

from fastapi import APIRouter, Depends, Query
from fastapi.responses import Response
from sqlalchemy import exists, or_, select
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.dependencies import get_current_admin
from app.core.responses import api_success
from app.models.admin import Admin
from app.models.chat import ChatMessage, ChatSession
from app.models.logs import AiRequestLog, OperationLog
from app.models.user import User

router = APIRouter()


@router.get("/chat/list")
def chat_list(
    keyword: str = Query(default=""),
    userId: int | None = Query(default=None),
    status: str = Query(default=""),
    dateFrom: datetime | None = Query(default=None),
    dateTo: datetime | None = Query(default=None),
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    rows = db.execute(
        _chat_query(keyword=keyword, user_id=userId, status=status, date_from=dateFrom, date_to=dateTo)
        .order_by(ChatSession.updated_at.desc())
        .limit(200)
    ).all()
    return api_success([_chat_row_dict(session, user) for session, user in rows])


@router.get("/chat/export")
def export_chats(
    keyword: str = Query(default=""),
    userId: int | None = Query(default=None),
    status: str = Query(default=""),
    dateFrom: datetime | None = Query(default=None),
    dateTo: datetime | None = Query(default=None),
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> Response:
    rows = db.execute(
        _chat_query(keyword=keyword, user_id=userId, status=status, date_from=dateFrom, date_to=dateTo)
        .order_by(ChatSession.updated_at.desc())
        .limit(1000)
    ).all()
    output = StringIO()
    writer = csv.writer(output)
    writer.writerow(["会话ID", "用户ID", "手机号", "姓名", "标题", "消息数", "最后消息时间", "更新时间"])
    for session, user in rows:
        writer.writerow(
            [
                session.id,
                session.user_id,
                user.phone if user else "",
                user.name if user else "",
                session.title,
                session.message_count,
                session.last_message_at,
                session.updated_at,
            ]
        )
    content = "\ufeff" + output.getvalue()
    return Response(
        content=content,
        media_type="text/csv; charset=utf-8",
        headers={"Content-Disposition": 'attachment; filename="chat_records.csv"'},
    )


@router.get("/chat/{session_id}")
def chat_detail(
    session_id: int,
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    session_row = db.execute(
        select(ChatSession, User)
        .join(User, User.id == ChatSession.user_id, isouter=True)
        .where(ChatSession.id == session_id)
    ).first()
    if session_row is None:
        from fastapi import HTTPException, status

        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="会话不存在")

    session, user = session_row
    messages = db.scalars(
        select(ChatMessage)
        .where(ChatMessage.session_id == session_id)
        .order_by(ChatMessage.created_at.asc(), ChatMessage.id.asc())
    ).all()
    ai_logs = db.scalars(
        select(AiRequestLog)
        .where(AiRequestLog.session_id == session_id)
        .order_by(AiRequestLog.created_at.asc(), AiRequestLog.id.asc())
    ).all()
    return api_success(
        {
            "session": _chat_row_dict(session, user),
            "messages": [_message_dict(item) for item in messages],
            "aiLogs": [_ai_log_dict(item, include_prompt=True) for item in ai_logs],
        }
    )


@router.get("/log/list")
def operation_logs(
    module: str = Query(default=""),
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    query = select(OperationLog).order_by(OperationLog.created_at.desc()).limit(200)
    if module:
        query = query.where(OperationLog.module == module)
    logs = db.scalars(query).all()
    return api_success(
        [
            {
                "id": item.id,
                "adminId": item.admin_id,
                "module": item.module,
                "action": item.action,
                "targetId": item.target_id,
                "result": item.result,
                "createdAt": item.created_at,
            }
            for item in logs
        ]
    )


@router.get("/ai-log/list")
def ai_logs(
    sessionId: int | None = Query(default=None),
    userId: int | None = Query(default=None),
    status: str = Query(default=""),
    db: Session = Depends(get_db),
    current_admin: Admin = Depends(get_current_admin),
) -> dict:
    query = select(AiRequestLog).order_by(AiRequestLog.created_at.desc()).limit(200)
    if sessionId is not None:
        query = query.where(AiRequestLog.session_id == sessionId)
    if userId is not None:
        query = query.where(AiRequestLog.user_id == userId)
    if status:
        query = query.where(AiRequestLog.status == status)
    logs = db.scalars(query).all()
    return api_success([_ai_log_dict(item) for item in logs])


def _chat_query(
    *,
    keyword: str,
    user_id: int | None,
    status: str,
    date_from: datetime | None,
    date_to: datetime | None,
):
    query = (
        select(ChatSession, User)
        .join(User, User.id == ChatSession.user_id, isouter=True)
        .where(ChatSession.is_deleted == 0)
    )
    if user_id is not None:
        query = query.where(ChatSession.user_id == user_id)
    if date_from is not None:
        query = query.where(ChatSession.updated_at >= date_from.replace(tzinfo=None))
    if date_to is not None:
        query = query.where(ChatSession.updated_at <= date_to.replace(tzinfo=None))
    if status:
        query = query.where(
            exists()
            .where(ChatMessage.session_id == ChatSession.id)
            .where(ChatMessage.message_status == status)
        )
    if keyword:
        like = f"%{keyword}%"
        query = query.where(
            or_(
                ChatSession.title.like(like),
                User.phone.like(like),
                User.name.like(like),
                exists()
                .where(ChatMessage.session_id == ChatSession.id)
                .where(ChatMessage.content.like(like)),
            )
        )
    return query


def _chat_row_dict(session: ChatSession, user: User | None) -> dict:
    return {
        "id": session.id,
        "userId": session.user_id,
        "userPhone": user.phone if user else "",
        "userName": user.name if user else "",
        "title": session.title,
        "messageCount": session.message_count,
        "lastMessageAt": session.last_message_at,
        "updatedAt": session.updated_at,
    }


def _message_dict(message: ChatMessage) -> dict:
    return {
        "id": message.id,
        "sessionId": message.session_id,
        "userId": message.user_id,
        "role": message.role,
        "content": message.content,
        "messageStatus": message.message_status,
        "tokenInput": message.token_input,
        "tokenOutput": message.token_output,
        "responseTimeMs": message.response_time_ms,
        "modelId": message.model_id,
        "createdAt": message.created_at,
    }


def _ai_log_dict(log: AiRequestLog, *, include_prompt: bool = False) -> dict:
    data = {
        "id": log.id,
        "sessionId": log.session_id,
        "messageId": log.message_id,
        "userId": log.user_id,
        "modelName": log.model_name,
        "knowledgeIds": log.knowledge_ids,
        "retrieveCount": log.retrieve_count,
        "inputToken": log.input_token,
        "outputToken": log.output_token,
        "totalToken": log.total_token,
        "costMs": log.cost_ms,
        "status": log.status,
        "errorMessage": log.error_message,
        "createdAt": log.created_at,
    }
    if include_prompt:
        data["prompt"] = log.prompt
    return data
