"""Private Core transport. Dash is the sole public Google callback."""

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.core.exceptions import NotFoundError
from src.domain.auth.models import User
from src.domain.auth.router import get_current_user
from src.domain.cloud.dependencies import require_cloud_internal_token
from src.domain.projects.repository import ProjectRepository
from src.domain.provider_auth.repository import ProviderAuthRepository
from src.domain.provider_auth.schemas import (
    AuthorizationCompleted,
    AuthorizationStarted,
    CompleteAuthorization,
    IdentityBind,
    IdentityConsume,
    IdentityStart,
    StartAuthorization,
)
from src.domain.provider_auth.service import ProviderAuthService

router = APIRouter(tags=["provider-authorization"])
SUPPORTED_OAUTH_PROVIDERS = {"google", "hubspot", "salesforce", "x_ads", "microsoft_ads"}


@router.post(
    "/v1/cloud/provider-auth/google/identity/start",
    dependencies=[Depends(require_cloud_internal_token)],
)
async def identity_start(body: IdentityStart, db: AsyncSession = Depends(get_db)):
    from src.domain.project_auth.provider_facade import google_identity_project
    from src.domain.provider_auth.identity import start_identity
    from src.integrations.cloud_control_client import get_cloud_client_for_workspace

    project, origins = await google_identity_project(db, body.project_id)
    cloud = await get_cloud_client_for_workspace(project.workspace_id, db)
    return await start_identity(
        ProviderAuthService(ProviderAuthRepository(db)),
        project=project,
        return_to=body.return_to,
        cloud_binding=body.cloud_binding,
        allowed_origins=origins,
        completion_url=f"{cloud.api_url}/v1/projects/{project.id}/auth/oauth/google/complete",
    )


@router.post("/api/provider-auth/google/identity/bind")
async def identity_bind(body: IdentityBind, db: AsyncSession = Depends(get_db)):
    from src.domain.provider_auth.identity import bind_identity

    return await bind_identity(
        ProviderAuthService(ProviderAuthRepository(db)), body.state, body.browser_binding
    )


@router.post(
    "/v1/cloud/provider-auth/google/identity/consume",
    dependencies=[Depends(require_cloud_internal_token)],
)
async def identity_consume(body: IdentityConsume, db: AsyncSession = Depends(get_db)):
    from src.domain.project_auth.provider_facade import google_identity_project
    from src.domain.provider_auth.identity import consume_identity

    await google_identity_project(db, body.project_id)
    return await consume_identity(
        ProviderAuthService(ProviderAuthRepository(db)),
        body.project_id,
        body.ticket,
        body.cloud_binding,
    )


@router.post(
    "/api/projects/{project_id}/provider-auth/{provider}/start",
    response_model=AuthorizationStarted,
)
async def start(
    provider: str,
    body: StartAuthorization,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    if provider not in SUPPORTED_OAUTH_PROVIDERS:
        raise NotFoundError("Provider authorization is not supported")
    project = await ProjectRepository(db).get_by_id(project_id)
    return await ProviderAuthService(ProviderAuthRepository(db), provider=provider).start(
        workspace_id=project.workspace_id, project_id=project_id, initiated_by=user.id, body=body
    )


@router.post("/api/provider-auth/{provider}/complete", response_model=AuthorizationCompleted)
async def complete(provider: str, body: CompleteAuthorization, db: AsyncSession = Depends(get_db)):
    # OAuth state + a server-generated HttpOnly browser binding authenticate this
    # callback even without a dashboard login cookie. No arbitrary return URLs.
    if provider not in SUPPORTED_OAUTH_PROVIDERS:
        raise NotFoundError("Provider authorization is not supported")
    return await ProviderAuthService(ProviderAuthRepository(db), provider=provider).complete(body)


@router.get("/api/projects/{project_id}/provider-auth/connections")
async def connections(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    db: AsyncSession = Depends(get_db),
):
    project = await ProjectRepository(db).get_by_id(project_id)
    rows = await ProviderAuthRepository(db).list_connections(project.workspace_id, project_id)
    return [
        {
            "id": row.id,
            "provider": row.provider,
            "status": row.status,
            "features": [
                g.family
                for g in await ProviderAuthRepository(db).grants(row.id)
                if g.status == "active"
            ],
        }
        for row in rows
    ]


@router.get("/api/projects/{project_id}/provider-auth/resume/{resume_id}")
async def resume(
    resume_id: UUID,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    project = await ProjectRepository(db).get_by_id(project_id)
    row = await ProviderAuthRepository(db).resume(
        project.workspace_id, project_id, resume_id, str(user.id)
    )
    if not row:
        raise NotFoundError("Authorization session not found")
    return {"status": row.status, "resume_id": row.id}
