"""Tool instance lifecycle API endpoints."""

import logging
import uuid

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession

from src.auth.dependencies import (
    _get_owned_project,
    _get_user,
    get_current_user_id,
    get_db_session,
)
from src.schemas.tool import StartInstanceRequest
from src.services.tool.instance_service import (
    delete_tool_instance,
    restart_tool_instance,
    start_tool_instance,
    stop_tool_instance,
)

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/projects", tags=["tool-instances"])


@router.post(
    "/{project_id}/repositories/{repo_id}/instances/{instance_id}/start",
    summary="Start instance",
    description="Start a tool instance using Docker Compose.",
)
async def start_instance(
    project_id: uuid.UUID,
    repo_id: uuid.UUID,
    instance_id: uuid.UUID,
    data: StartInstanceRequest | None = None,
    user_id: uuid.UUID = Depends(get_current_user_id),
    session: AsyncSession = Depends(get_db_session),
) -> dict:
    _user = await _get_user(session, user_id)
    _project = await _get_owned_project(project_id, user_id, session)
    try:
        return await start_tool_instance(
            session, user_id, project_id, repo_id, instance_id, data
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
    except RuntimeError as exc:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)
        )


@router.post(
    "/{project_id}/repositories/{repo_id}/instances/{instance_id}/stop",
    summary="Stop instance",
    description="Stop a running tool instance.",
)
async def stop_instance(
    project_id: uuid.UUID,
    repo_id: uuid.UUID,
    instance_id: uuid.UUID,
    user_id: uuid.UUID = Depends(get_current_user_id),
    session: AsyncSession = Depends(get_db_session),
) -> dict:
    _user = await _get_user(session, user_id)
    _project = await _get_owned_project(project_id, user_id, session)
    try:
        return await stop_tool_instance(session, user_id, project_id, repo_id, instance_id)
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc))


@router.post(
    "/{project_id}/repositories/{repo_id}/instances/{instance_id}/restart",
    summary="Restart instance",
    description="Restart a tool instance.",
)
async def restart_instance(
    project_id: uuid.UUID,
    repo_id: uuid.UUID,
    instance_id: uuid.UUID,
    user_id: uuid.UUID = Depends(get_current_user_id),
    session: AsyncSession = Depends(get_db_session),
) -> dict:
    _user = await _get_user(session, user_id)
    _project = await _get_owned_project(project_id, user_id, session)
    try:
        return await restart_tool_instance(
            session, user_id, project_id, repo_id, instance_id
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc))
    except RuntimeError as exc:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)
        )


@router.delete(
    "/{project_id}/repositories/{repo_id}/instances/{instance_id}",
    summary="Delete instance",
    description="Delete a tool instance and remove its Docker containers and files.",
)
async def delete_instance(
    project_id: uuid.UUID,
    repo_id: uuid.UUID,
    instance_id: uuid.UUID,
    force: bool = False,
    user_id: uuid.UUID = Depends(get_current_user_id),
    session: AsyncSession = Depends(get_db_session),
) -> None:
    _user = await _get_user(session, user_id)
    _project = await _get_owned_project(project_id, user_id, session)
    try:
        await delete_tool_instance(
            session, user_id, project_id, repo_id, instance_id, force
        )
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc))
    except RuntimeError as exc:
        detail = str(exc)
        if "uncommitted changes" in detail.lower():
            raise HTTPException(
                status_code=status.HTTP_409_CONFLICT,
                detail={
                    "message": "Repository has uncommitted changes",
                    "changed_files": detail,
                    "force_required": True,
                },
            )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=detail
        )
