"""Read-only aggregate view over existing project capability state."""

from __future__ import annotations

from typing import Any
from uuid import UUID

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

from src.config import get_settings
from src.core.database import async_session_factory, 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.capabilities.adapters import (
    AuthV2Provisioner,
    FeaturePackProvisioner,
    FormsProvisioner,
)
from src.domain.capabilities.lifecycle import CapabilityStatus, ProvisionPlan
from src.domain.capabilities.native_adapters import (
    FilesProvisioner,
    NotificationsProvisioner,
    RecordsProvisioner,
    SecretsProvisioner,
    WebhooksProvisioner,
)

router = APIRouter(prefix="/api/projects/{project_id}/capabilities", tags=["capability-lifecycle"])


def build_capability_provisioners(
    db: AsyncSession, settings: Any
) -> tuple[
    AuthV2Provisioner,
    FormsProvisioner,
    FeaturePackProvisioner,
    FilesProvisioner,
    RecordsProvisioner,
    NotificationsProvisioner,
    WebhooksProvisioner,
    SecretsProvisioner,
]:
    """Construct the registered capability provisioners for one project.

    ``FeaturePackProvisioner`` is given the other two by key so its
    ``runtime_requirements()`` can aggregate requirements from whichever
    capabilities an installed pack actually depends on, without importing any
    hosting- or auth-specific code itself.
    """
    auth = AuthV2Provisioner(
        db,
        cloud_base_url=settings.cloud_control_api_url,
        cloud_token=settings.cloud_internal_token,
    )
    forms = FormsProvisioner(db)
    files = FilesProvisioner(db)
    records = RecordsProvisioner(db)
    notifications = NotificationsProvisioner(db)
    webhooks = WebhooksProvisioner(db)
    secrets = SecretsProvisioner(db)
    feature_packs = FeaturePackProvisioner(
        db,
        db_factory=async_session_factory,
        capability_providers={
            "auth": auth,
            "forms": forms,
            "files": files,
            "records": records,
            "notifications": notifications,
            "webhooks": webhooks,
            "secrets": secrets,
        },
    )
    return auth, forms, feature_packs, files, records, notifications, webhooks, secrets


@router.get("/status", response_model=list[CapabilityStatus])
async def get_project_capability_status(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> list[CapabilityStatus]:
    """Return lifecycle status without changing any specialized capability state."""
    settings = get_settings()
    provisioners = build_capability_provisioners(db, settings)
    return [await provisioner.status(project_id) for provisioner in provisioners]


@router.get("/plan", response_model=list[ProvisionPlan])
async def get_project_capability_plan(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> list[ProvisionPlan]:
    """Return what ``apply()``/``reconcile()`` would do for each capability right
    now, without doing it -- the same provisioners /status reads, one deterministic
    plan per capability (action + changes), inspectable before any mutation."""
    settings = get_settings()
    provisioners = build_capability_provisioners(db, settings)
    return [await provisioner.plan(project_id) for provisioner in provisioners]
