"""Voice domain — dashboard routes. Core decides; Cloud executes."""
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.exceptions import NotFoundError
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.projects.repository import ProjectRepository
from src.domain.voice.repository import VoiceRepository
from src.domain.voice.schemas import (
    PhoneNumberResponse,
    UpdateVoiceConfigRequest,
    UpsertPhoneNumberRequest,
    UpsertVoiceAgentRequest,
    VoiceAgentResponse,
    VoiceConfigResponse,
)
from src.domain.voice.service import VoiceService
from src.integrations.cloud_control_client import CloudControlClient

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


def _get_service(db: AsyncSession = Depends(get_db)) -> VoiceService:
    return VoiceService(repo=VoiceRepository(db), cloud_client=CloudControlClient())


async def _workspace_id(db: AsyncSession, project_id: UUID) -> UUID:
    project = await ProjectRepository(db).get_by_id(project_id)
    if not project:
        raise NotFoundError("Project not found")
    return project.workspace_id


@router.get("/config", response_model=VoiceConfigResponse)
async def get_voice_config(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: VoiceService = Depends(_get_service),
) -> VoiceConfigResponse:
    ws = await _workspace_id(db, project_id)
    return await svc.get_or_create_config(project_id, ws)


@router.patch("/config", response_model=VoiceConfigResponse)
async def update_voice_config(
    body: UpdateVoiceConfigRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: VoiceService = Depends(_get_service),
) -> VoiceConfigResponse:
    ws = await _workspace_id(db, project_id)
    return await svc.update_config(project_id, ws, body)


@router.get("/agents", response_model=list[VoiceAgentResponse])
async def list_voice_agents(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: VoiceService = Depends(_get_service),
) -> list[VoiceAgentResponse]:
    return await svc.list_agents(project_id)


@router.put("/agents", response_model=VoiceAgentResponse)
async def upsert_voice_agent(
    body: UpsertVoiceAgentRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: VoiceService = Depends(_get_service),
) -> VoiceAgentResponse:
    ws = await _workspace_id(db, project_id)
    return await svc.upsert_agent(project_id, ws, body)


@router.put("/agents/{agent_id}", response_model=VoiceAgentResponse)
async def update_voice_agent(
    agent_id: UUID,
    body: UpsertVoiceAgentRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: VoiceService = Depends(_get_service),
) -> VoiceAgentResponse:
    ws = await _workspace_id(db, project_id)
    return await svc.upsert_agent(project_id, ws, body, agent_id)


@router.get("/numbers", response_model=list[PhoneNumberResponse])
async def list_phone_numbers(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: VoiceService = Depends(_get_service),
) -> list[PhoneNumberResponse]:
    return await svc.list_numbers(project_id)


@router.put("/numbers", response_model=PhoneNumberResponse)
async def upsert_phone_number(
    body: UpsertPhoneNumberRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: VoiceService = Depends(_get_service),
) -> PhoneNumberResponse:
    ws = await _workspace_id(db, project_id)
    return await svc.upsert_number(project_id, ws, body)


@router.put("/numbers/{number_id}", response_model=PhoneNumberResponse)
async def update_phone_number(
    number_id: UUID,
    body: UpsertPhoneNumberRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    svc: VoiceService = Depends(_get_service),
) -> PhoneNumberResponse:
    ws = await _workspace_id(db, project_id)
    return await svc.upsert_number(project_id, ws, body, number_id)
