from typing import Optional

from fastapi import APIRouter, HTTPException

from vdash.core.exceptions import NotFoundError
from vdash.modules.sql import (
    CreateSqlQueryRequest,
    GenerateSqlRequest,
    SqlConversationResponse,
    SqlMessageResponse,
    SqlQueryResponse,
    UpdateSqlQueryRequest,
)
from vdash.presentation.api.v1.dependencies import PaginationQueryDep, SqlServiceDep
from vdash.shared import MessageResponse, PaginatedResult

# Conversation
router_conversation = APIRouter(prefix="/sql-conversation", tags=["SQL Conversation"])


@router_conversation.get(
    "/",
    response_model=PaginatedResult[SqlConversationResponse],
)
async def list_conversations(
    sql_service: SqlServiceDep,
    pagination: PaginationQueryDep,
    user_db_uuid: Optional[str] = None,
):
    conversations = await sql_service.list_conversations(pagination, user_db_uuid)

    return PaginatedResult[SqlConversationResponse](
        items=[
            SqlConversationResponse(
                uuid=conv.uuid,
                user_db_uuid=conv.user_db.uuid,
                title=conv.title,
                created_at=conv.created_at,
                updated_at=conv.updated_at,
            )
            for conv in conversations.items
        ],
        page=conversations.page,
        page_size=conversations.page_size,
        total=conversations.total,
    )


@router_conversation.post(
    "/",
    response_model=SqlMessageResponse,
    responses={404: {"description": "Not Found"}},
)
async def generate_sql(
    request: GenerateSqlRequest,
    sql_service: SqlServiceDep,
) -> SqlMessageResponse:
    try:
        return await sql_service.generate_sql(request)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))


@router_conversation.get(
    "/{conversation_uuid}",
    response_model=SqlConversationResponse,
    responses={404: {"description": "Not Found"}},
)
async def get_conversation(
    conversation_uuid: str,
    sql_service: SqlServiceDep,
):
    try:
        conv = await sql_service.get_conversation(conversation_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return SqlConversationResponse(
        uuid=conv.uuid,
        user_db_uuid=conv.user_db.uuid,
        title=conv.title,
        created_at=conv.created_at,
        updated_at=conv.updated_at,
    )


@router_conversation.delete(
    "/{conversation_uuid}",
    response_model=MessageResponse,
    responses={404: {"description": "Not Found"}},
)
async def delete_conversation(
    conversation_uuid: str,
    sql_service: SqlServiceDep,
):
    try:
        await sql_service.delete_conversation(conversation_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return MessageResponse(detail="Conversation deleted successfully")


@router_conversation.get(
    "/{conversation_uuid}/messages",
    response_model=PaginatedResult[SqlMessageResponse],
    responses={404: {"description": "Not Found"}},
)
async def list_messages(
    conversation_uuid: str,
    sql_service: SqlServiceDep,
    pagination: PaginationQueryDep,
):
    try:
        messages = await sql_service.list_messages(conversation_uuid, pagination)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return PaginatedResult[SqlMessageResponse](
        items=[
            SqlMessageResponse(
                uuid=message.uuid,
                role=message.role,
                content=message.content,
                created_at=message.created_at,
            )
            for message in messages.items
        ],
        page=messages.page,
        page_size=messages.page_size,
        total=messages.total,
    )


# SqlQuery
router_sql = APIRouter(prefix="/sql", tags=["SQL"])


@router_sql.get(
    "/",
    response_model=PaginatedResult[SqlQueryResponse],
)
async def list_queries(
    service: SqlServiceDep,
    pagination: PaginationQueryDep,
    conversation_uuid: Optional[str] = None,
):
    queries = await service.list_queries(pagination, conversation_uuid)

    return PaginatedResult[SqlQueryResponse](
        items=[
            SqlQueryResponse(
                uuid=query.uuid,
                user_db_uuid=query.user_db.uuid,
                name=query.name,
                sql=query.sql,
                created_at=query.created_at,
                updated_at=query.updated_at,
            )
            for query in queries.items
        ],
        page=queries.page,
        page_size=queries.page_size,
        total=queries.total,
    )


@router_sql.post(
    "/",
    response_model=SqlQueryResponse,
)
async def create_query(
    request: CreateSqlQueryRequest,
    service: SqlServiceDep,
):
    try:
        query = await service.create_query(request)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return SqlQueryResponse(
        uuid=query.uuid,
        user_db_uuid=query.user_db.uuid,
        name=query.name,
        sql=query.sql,
        created_at=query.created_at,
        updated_at=query.updated_at,
    )


@router_sql.get(
    "/{query_uuid}",
    response_model=SqlQueryResponse,
    responses={404: {"description": "Not Found"}},
)
async def get_query(
    query_uuid: str,
    service: SqlServiceDep,
):
    try:
        query = await service.get_query(query_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return SqlQueryResponse(
        uuid=query.uuid,
        user_db_uuid=query.user_db.uuid,
        name=query.name,
        sql=query.sql,
        created_at=query.created_at,
        updated_at=query.updated_at,
    )


@router_sql.put(
    "/{query_uuid}",
    response_model=SqlQueryResponse,
    responses={404: {"description": "Not Found"}},
)
async def update_query(
    query_uuid: str,
    request: UpdateSqlQueryRequest,
    service: SqlServiceDep,
):
    try:
        query = await service.update_query(query_uuid, request)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return SqlQueryResponse(
        uuid=query.uuid,
        user_db_uuid=query.user_db.uuid,
        name=query.name,
        sql=query.sql,
        created_at=query.created_at,
        updated_at=query.updated_at,
    )


@router_sql.delete(
    "/{query_uuid}",
    response_model=MessageResponse,
    responses={404: {"description": "Not Found"}},
)
async def delete_query(
    query_uuid: str,
    service: SqlServiceDep,
):
    try:
        await service.delete_query(query_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return MessageResponse(detail="Query deleted successfully")
