"""External Connections domain — HTTP routes."""
from __future__ import annotations

from uuid import UUID

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

from src.core.database import get_db
from src.core.dependencies import require_active_billing_for_project_id
from src.domain.auth.models import User
from src.domain.auth.router import get_current_user
from src.domain.cloud_infra.repository import (
    CFAccountRepository,
    CloudInstanceRepository,
    CloudShardRepository,
    ProjectCloudAssignmentRepository,
    WorkspaceCloudAssignmentRepository,
)
from src.domain.cloud_infra.service import CloudInfraService
from src.domain.external_connections.repository import ExternalConnectionRepository
from src.domain.external_connections.schemas import (
    ConnectionResponse,
    CreateConnectionRequest,
    SchemaSnapshotResponse,
    TestConnectionResponse,
    UpdateConnectionRequest,
)
from src.domain.external_connections.service import ExternalConnectionService
from src.domain.projects.repository import ProjectRepository
from src.domain.workspaces.repository import WorkspaceRepository
from src.integrations.cloud_control_client import CloudControlClient

router = APIRouter(
    prefix="/api/projects/{project_id}/connections",
    tags=["external-connections"],
)


def _get_service(db: AsyncSession = Depends(get_db)) -> ExternalConnectionService:
    return ExternalConnectionService(
        repo=ExternalConnectionRepository(db),
        cloud_client=CloudControlClient(),
        cloud_infra_svc=CloudInfraService(
            cf_account_repo=CFAccountRepository(db),
            instance_repo=CloudInstanceRepository(db),
            assignment_repo=WorkspaceCloudAssignmentRepository(db),
            shard_repo=CloudShardRepository(db),
            project_shard_repo=ProjectCloudAssignmentRepository(db),
        ),
    )


@router.get("", response_model=list[ConnectionResponse])
async def list_connections(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> list[ConnectionResponse]:
    return await svc.list_connections(project_id)


@router.get("/{name}", response_model=ConnectionResponse)
async def get_connection(
    name: str,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> ConnectionResponse:
    return await svc.get_connection(project_id, name)


@router.post("", response_model=ConnectionResponse, status_code=201)
async def create_connection(
    body: CreateConnectionRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: ExternalConnectionService = Depends(_get_service),
) -> ConnectionResponse:
    proj = await ProjectRepository(db).get_by_id(project_id)
    ws = await WorkspaceRepository(db).get_by_id(proj.workspace_id)
    plan_slug = getattr(ws, "selected_plan_slug", None) if ws else None
    return await svc.create_connection(
        project_id=project_id,
        workspace_id=proj.workspace_id,
        body=body,
        plan_slug=plan_slug,
    )


@router.patch("/{name}", response_model=ConnectionResponse)
async def update_connection(
    name: str,
    body: UpdateConnectionRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> ConnectionResponse:
    return await svc.update_connection(project_id, name, body)


@router.delete("/{name}", status_code=204, response_model=None)
async def delete_connection(
    name: str,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> None:
    await svc.delete_connection(project_id, name)


@router.get("/{name}/schema", response_model=SchemaSnapshotResponse)
async def get_schema(
    name: str,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> SchemaSnapshotResponse:
    return await svc.get_schema(project_id, name)


@router.post("/{name}/test", response_model=TestConnectionResponse)
async def test_connection(
    name: str,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> TestConnectionResponse:
    return await svc.test_connection(project_id, name)


@router.post("/{name}/refresh-schema", response_model=ConnectionResponse)
async def refresh_schema(
    name: str,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ExternalConnectionService = Depends(_get_service),
) -> ConnectionResponse:
    return await svc.refresh_schema(project_id, name)
