from __future__ import annotations

import os
from urllib.parse import urlparse

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse

from jarvis_finance.api.routers import budget, cash, crypto, crypto_trader, equity, health, market, overview, positions, reports, system
from jarvis_finance.api.security import WRITE_METHODS, is_write_request_allowed, resolve_write_mode

LOCAL_ORIGINS = [
    "http://localhost:5173",
    "http://127.0.0.1:5173",
    "http://100.85.29.67:5173",
    "http://agent.tailbd371b.ts.net:5173",
    "http://localhost:8503",
    "http://127.0.0.1:8503",
]
READ_ONLY_POST_PATHS = {"/api/portfolio/ingestion/preview", "/api/portfolio/policy/preview"}


def _is_safe_local_origin(origin: str) -> bool:
    parsed = urlparse(origin)
    if parsed.scheme != "http" or not parsed.hostname or not parsed.port:
        return False
    hostname = parsed.hostname.lower()
    if hostname in {"localhost", "127.0.0.1"}:
        return True
    if hostname.startswith("100."):
        return True
    if hostname.endswith(".ts.net"):
        return True
    return False


def build_local_origins(environ: dict[str, str] | None = None) -> list[str]:
    env = environ or os.environ
    origins = list(LOCAL_ORIGINS)
    for raw_origin in env.get("JARVIS_FINANCE_CORS_ORIGINS", "").split(","):
        origin = raw_origin.strip().rstrip("/")
        if origin and _is_safe_local_origin(origin) and origin not in origins:
            origins.append(origin)
    return origins


def create_app(*, write_mode: str | None = None) -> FastAPI:
    active_write_mode = resolve_write_mode(write_mode)
    app = FastAPI(
        title="JARVIS Finance API",
        version="0.1.0",
        description="Read-only FastAPI v0 skeleton for the future Vue User Dashboard.",
    )
    app.add_middleware(
        CORSMiddleware,
        allow_origins=build_local_origins(),
        allow_credentials=False,
        allow_methods=["GET", "POST"] if active_write_mode == "disabled" else ["GET", "POST", "PUT", "PATCH", "DELETE"],
        allow_headers=["*"],
    )

    @app.middleware("http")
    async def block_untrusted_writes(request: Request, call_next):
        read_only_post = request.method == "POST" and request.url.path in READ_ONLY_POST_PATHS
        if request.method in WRITE_METHODS and not read_only_post and not is_write_request_allowed(request, active_write_mode):
            return JSONResponse(status_code=403, content={"detail": "write_operations_disabled"})
        return await call_next(request)

    app.state.write_mode = active_write_mode
    for router in (health.router, overview.router, crypto.router, crypto_trader.router, equity.router, cash.router, reports.router, positions.router, budget.router, system.router, market.router):
        app.include_router(router, prefix="/api")
    return app


app = create_app()
