"""
FastAPI routes for Compliance Scope persistence.

Stores the tenant's scope decision (frameworks, regulations, industry context)
in sdk_states.state->compliance_scope as JSONB.

Endpoints:
- GET /v1/compliance-scope?tenant_id=... → returns scope or 404
- POST /v1/compliance-scope → UPSERT scope (idempotent)
"""

import json
import logging
from typing import Any, Optional

from fastapi import APIRouter, HTTPException, Header
from pydantic import BaseModel
from sqlalchemy import text

from database import SessionLocal

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/v1/compliance-scope", tags=["compliance-scope"])


# =============================================================================
# REQUEST / RESPONSE MODELS
# =============================================================================

class ComplianceScopeRequest(BaseModel):
    """Scope selection submitted by the frontend wizard."""
    scope: dict[str, Any]
    tenant_id: Optional[str] = None


class ComplianceScopeResponse(BaseModel):
    """Persisted scope object returned to the frontend."""
    tenant_id: str
    scope: dict[str, Any]
    updated_at: str
    created_at: str


# =============================================================================
# HELPERS
# =============================================================================

def _get_tid(
    x_tenant_id: Optional[str],
    query_tenant_id: str,
) -> str:
    return x_tenant_id or query_tenant_id or "default"


def _row_to_response(row) -> ComplianceScopeResponse:
    """Convert a DB row (tenant_id, scope, created_at, updated_at) to response."""
    return ComplianceScopeResponse(
        tenant_id=row[0],
        scope=row[1] if isinstance(row[1], dict) else {},
        created_at=str(row[2]),
        updated_at=str(row[3]),
    )


# =============================================================================
# ROUTES
# =============================================================================

@router.get("", response_model=ComplianceScopeResponse)
async def get_compliance_scope(
    tenant_id: str = "default",
    x_tenant_id: Optional[str] = Header(None, alias="X-Tenant-ID"),
):
    """Return the persisted compliance scope for a tenant, or 404 if not set."""
    tid = _get_tid(x_tenant_id, tenant_id)
    db = SessionLocal()
    try:
        row = db.execute(
            text("""SELECT tenant_id,
                      state->'compliance_scope' AS scope,
                      created_at,
                      updated_at
               FROM sdk_states
               WHERE tenant_id = :tid
                 AND state ? 'compliance_scope'"""),
            {"tid": tid},
        ).fetchone()

        if not row or row[1] is None:
            raise HTTPException(status_code=404, detail="Compliance scope not found")

        return _row_to_response(row)
    finally:
        db.close()


@router.post("", response_model=ComplianceScopeResponse)
async def upsert_compliance_scope(
    body: ComplianceScopeRequest,
    tenant_id: str = "default",
    x_tenant_id: Optional[str] = Header(None, alias="X-Tenant-ID"),
):
    """Create or update the compliance scope for a tenant (UPSERT)."""
    tid = _get_tid(x_tenant_id, body.tenant_id or tenant_id)
    scope_json = json.dumps(body.scope)

    db = SessionLocal()
    try:
        db.execute(
            text("""INSERT INTO sdk_states (tenant_id, state)
               VALUES (:tid, jsonb_build_object('compliance_scope', :scope::jsonb))
               ON CONFLICT (tenant_id) DO UPDATE
                 SET state = sdk_states.state || jsonb_build_object('compliance_scope', :scope::jsonb),
                     updated_at = NOW()"""),
            {"tid": tid, "scope": scope_json},
        )
        db.commit()

        row = db.execute(
            text("""SELECT tenant_id,
                      state->'compliance_scope' AS scope,
                      created_at,
                      updated_at
               FROM sdk_states
               WHERE tenant_id = :tid"""),
            {"tid": tid},
        ).fetchone()

        return _row_to_response(row)
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to upsert compliance scope: {e}")
        raise HTTPException(status_code=500, detail="Failed to save compliance scope")
    finally:
        db.close()
