from uuid import UUID

from fastapi import APIRouter, Depends

from app.api.deps import AsyncSession, CurrentUser, get_db, require_tenant
from app.api.permissions import require_permissions
from app.permissions.definitions import PROVIDERS_MANAGE, PROVIDERS_VIEW, SENDERS_MANAGE, SENDERS_VIEW
from app.schemas.common import (
    ProviderCreate,
    ProviderOut,
    ProviderStatusOut,
    ProviderUpdate,
    SenderCreate,
    SenderOut,
)
from app.services.monitoring_service import MonitoringService
from app.services.provider_service import ProviderService

router = APIRouter()


@router.get("", response_model=list[ProviderOut])
async def list_providers(
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    _: CurrentUser = Depends(require_permissions(PROVIDERS_VIEW)),
):
    return await ProviderService(session).list(tenant_id)


@router.post("", response_model=ProviderOut, status_code=201)
async def create_provider(
    body: ProviderCreate,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(require_permissions(PROVIDERS_MANAGE)),
):
    return await ProviderService(session).create(
        tenant_id, body.model_dump(), actor_id=user.user_id
    )


@router.get("/status", response_model=list[ProviderStatusOut])
async def providers_status(
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    _: CurrentUser = Depends(require_permissions(PROVIDERS_VIEW)),
):
    return await MonitoringService(session).providers_status(tenant_id)


@router.get("/{provider_id}", response_model=ProviderOut)
async def get_provider(
    provider_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    _: CurrentUser = Depends(require_permissions(PROVIDERS_VIEW)),
):
    return await ProviderService(session).get(tenant_id, provider_id)


@router.patch("/{provider_id}", response_model=ProviderOut)
async def update_provider(
    provider_id: UUID,
    body: ProviderUpdate,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(require_permissions(PROVIDERS_MANAGE)),
):
    return await ProviderService(session).update(
        tenant_id,
        provider_id,
        body.model_dump(exclude_unset=True),
        actor_id=user.user_id,
    )


@router.delete("/{provider_id}", status_code=204)
async def delete_provider(
    provider_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(require_permissions(PROVIDERS_MANAGE)),
):
    await ProviderService(session).delete(tenant_id, provider_id, actor_id=user.user_id)


@router.get("/{provider_id}/balance")
async def provider_balance(
    provider_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    _: CurrentUser = Depends(require_permissions(PROVIDERS_VIEW)),
):
    balance = await ProviderService(session).get_balance(tenant_id, provider_id)
    return {"provider_id": provider_id, "balance": balance}


@router.post("/{provider_id}/health")
async def provider_health(
    provider_id: UUID,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    _: CurrentUser = Depends(require_permissions(PROVIDERS_VIEW)),
):
    return await ProviderService(session).health_probe(tenant_id, provider_id)


@router.post("/senders", response_model=SenderOut, status_code=201)
async def create_sender(
    body: SenderCreate,
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    user: CurrentUser = Depends(require_permissions(SENDERS_MANAGE)),
):
    return await ProviderService(session).create_sender(
        tenant_id, body.model_dump(), actor_id=user.user_id
    )


@router.get("/senders/list", response_model=list[SenderOut])
async def list_senders(
    tenant_id: UUID = Depends(require_tenant),
    session: AsyncSession = Depends(get_db),
    _: CurrentUser = Depends(require_permissions(SENDERS_VIEW)),
):
    return await ProviderService(session).list_senders(tenant_id)
