from fastapi import FastAPI, Request
from fastapi.responses import PlainTextResponse

from app.analyzer import analyze
from app.config import settings
from app.schemas import AnalyzeRequest, AnalyzeResponse
from app.webhooks_chatwoot import router as chatwoot_router
from app.db import init_db
from app.admin_ui.router import router as admin_dashboard_router
from app.api.internal import router as internal_api_router


def _looks_like_invalid_uuid_error(exc: Exception) -> bool:
    text_value = str(exc)
    lowered = text_value.lower()
    return (
        "invalid input syntax for type uuid" in lowered
        or "badly formed hexadecimal uuid" in lowered
        or "valueerror: badly formed hexadecimal uuid" in lowered
        or "could not parse uuid" in lowered
    )


def _is_browser_request(request: Request) -> bool:
    accept = str(request.headers.get("accept") or "")
    return "text/html" in accept and "application/json" not in accept


app = FastAPI(
    title="ClientFlow MVP",
    description="Motor de contexto comercial com Qwen3 30B + regras ClientFlow.",
    version="0.1.0",
)



@app.middleware("http")
async def security_headers_middleware(request: Request, call_next):
    response = await call_next(request)
    response.headers.setdefault("X-Content-Type-Options", "nosniff")
    response.headers.setdefault("X-Frame-Options", "DENY")
    response.headers.setdefault("Referrer-Policy", "strict-origin-when-cross-origin")
    response.headers.setdefault("Permissions-Policy", "camera=(), microphone=(), geolocation=()")
    # A UI atual carrega Bootstrap, Bootstrap Icons e HTMX por CDN.
    # A CSP deve refletir explicitamente essas dependências para evitar erros reais
    # no browser/Playwright, mantendo frame-ancestors e defaults restritos.
    response.headers.setdefault(
        "Content-Security-Policy",
        "default-src 'self'; "
        "img-src 'self' data:; "
        "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; "
        "style-src-elem 'self' 'unsafe-inline' https://cdn.jsdelivr.net; "
        "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com; "
        "script-src-elem 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com; "
        "font-src 'self' data: https://cdn.jsdelivr.net; "
        "connect-src 'self' ws: wss:; "
        "frame-ancestors 'none'",
    )
    path = str(request.url.path or "")
    if path in {"/", "/tasks", "/customers", "/opportunities", "/finance", "/system", "/settings"} or path.startswith(("/tasks", "/customers", "/opportunities", "/outbox", "/finance", "/financeiro")):
        response.headers.setdefault("Cache-Control", "private, no-store")
    return response


@app.exception_handler(Exception)
async def controlled_exception_handler(request: Request, exc: Exception):
    if _looks_like_invalid_uuid_error(exc):
        return PlainTextResponse("Identificador inválido.", status_code=422)
    # Keep unexpected errors visible during development/test while avoiding raw tracebacks in HTML.
    raise exc

app.include_router(chatwoot_router)
app.include_router(internal_api_router)


@app.on_event("startup")
async def startup_event() -> None:
    init_db()


@app.get("/health")
async def health() -> dict:
    return {
        "status": "ok",
        "app": settings.app_name,
        "env": settings.env,
        "model": settings.openrouter_model,
    }


@app.post("/analyze", response_model=AnalyzeResponse)
async def analyze_endpoint(request: AnalyzeRequest) -> AnalyzeResponse:
    return await analyze(request)

app.include_router(admin_dashboard_router)
