from typing import Optional

from fastapi import APIRouter, HTTPException

from vdash.core.exceptions import NotFoundError
from vdash.modules.chart import (
    ChartConversationResponse,
    ChartMessageResponse,
    ChartResponse,
    CreateChartRequest,
    UpdateChartRequest,
)
from vdash.presentation.api.v1.dependencies import ChartServiceDep, PaginationQueryDep
from vdash.shared import MessageResponse, PaginatedResult

# ── Conversation ──────────────────────────────────────────────────
router_conversation = APIRouter(
    prefix="/chart-conversation", tags=["Chart Conversation"]
)


@router_conversation.get(
    "/",
    response_model=PaginatedResult[ChartConversationResponse],
)
async def list_conversations(
    service: ChartServiceDep,
    pagination: PaginationQueryDep,
    sql_query_uuid: Optional[str] = None,
):
    conversations = await service.list_conversations(pagination, sql_query_uuid)

    return PaginatedResult[ChartConversationResponse](
        items=[
            ChartConversationResponse(
                uuid=conv.uuid,
                sql_query_uuid=conv.sql_query.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.get(
    "/{conversation_uuid}",
    response_model=ChartConversationResponse,
    responses={404: {"description": "Not Found"}},
)
async def get_conversation(
    conversation_uuid: str,
    service: ChartServiceDep,
):
    try:
        conv = await service.get_conversation(conversation_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return ChartConversationResponse(
        uuid=conv.uuid,
        sql_query_uuid=conv.sql_query.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,
    service: ChartServiceDep,
):
    try:
        await 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[ChartMessageResponse],
    responses={404: {"description": "Not Found"}},
)
async def list_messages(
    conversation_uuid: str,
    service: ChartServiceDep,
    pagination: PaginationQueryDep,
):
    try:
        messages = await service.list_messages(conversation_uuid, pagination)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return PaginatedResult[ChartMessageResponse](
        items=[
            ChartMessageResponse(
                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,
    )


# ── Chart ─────────────────────────────────────────────────────────
router_chart = APIRouter(prefix="/chart", tags=["Chart"])


@router_chart.get(
    "/",
    response_model=PaginatedResult[ChartResponse],
)
async def list_charts(
    service: ChartServiceDep,
    pagination: PaginationQueryDep,
    conversation_uuid: Optional[str] = None,
):
    charts = await service.list_charts(pagination, conversation_uuid)

    return PaginatedResult[ChartResponse](
        items=[
            ChartResponse(
                uuid=chart.uuid,
                sql_query_uuid=chart.sql_query.uuid if chart.sql_query else None,
                name=chart.name,
                vega_chart=chart.vega_chart,
                created_at=chart.created_at,
                updated_at=chart.updated_at,
            )
            for chart in charts.items
        ],
        page=charts.page,
        page_size=charts.page_size,
        total=charts.total,
    )


@router_chart.post(
    "/",
    response_model=ChartResponse,
)
async def create_chart(
    request: CreateChartRequest,
    service: ChartServiceDep,
):
    try:
        chart = await service.create_chart(request)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return ChartResponse(
        uuid=chart.uuid,
        sql_query_uuid=chart.sql_query.uuid if chart.sql_query else None,
        name=chart.name,
        vega_chart=chart.vega_chart,
        created_at=chart.created_at,
        updated_at=chart.updated_at,
    )


@router_chart.get(
    "/{chart_uuid}",
    response_model=ChartResponse,
    responses={404: {"description": "Not Found"}},
)
async def get_chart(
    chart_uuid: str,
    service: ChartServiceDep,
):
    try:
        chart = await service.get_chart(chart_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return ChartResponse(
        uuid=chart.uuid,
        sql_query_uuid=chart.sql_query.uuid if chart.sql_query else None,
        name=chart.name,
        vega_chart=chart.vega_chart,
        created_at=chart.created_at,
        updated_at=chart.updated_at,
    )


@router_chart.put(
    "/{chart_uuid}",
    response_model=ChartResponse,
    responses={404: {"description": "Not Found"}},
)
async def update_chart(
    chart_uuid: str,
    request: UpdateChartRequest,
    service: ChartServiceDep,
):
    try:
        chart = await service.update_chart(chart_uuid, request)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))

    return ChartResponse(
        uuid=chart.uuid,
        sql_query_uuid=chart.sql_query.uuid if chart.sql_query else None,
        name=chart.name,
        vega_chart=chart.vega_chart,
        created_at=chart.created_at,
        updated_at=chart.updated_at,
    )


@router_chart.delete(
    "/{chart_uuid}",
    response_model=MessageResponse,
    responses={404: {"description": "Not Found"}},
)
async def delete_chart(
    chart_uuid: str,
    service: ChartServiceDep,
):
    try:
        await service.delete_chart(chart_uuid)
    except NotFoundError as e:
        raise HTTPException(status_code=404, detail=str(e))
    return MessageResponse(detail="Chart deleted successfully")
