import uuid
import logging
from pathlib import Path
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request, Response, status
from fastapi.responses import FileResponse, JSONResponse, PlainTextResponse, RedirectResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from slowapi.errors import RateLimitExceeded
from slowapi import _rate_limit_exceeded_handler
from app.config import settings
from app.security.rate_limit import limiter
from app.models.database import create_tables
from app.routers import health, auth, convert, admin, contact, account, playground, reconciliation

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

FRONTEND_DIR = Path(__file__).resolve().parent.parent / "frontend"


@asynccontextmanager
async def lifespan(app: FastAPI):
    create_tables()
    logger.info("Tablas de base de datos creadas/verificadas")
    yield


app = FastAPI(
    title="MT2MX API",
    description="Convierte mensajes SWIFT MT940/MT950 a formato ISO 20022 camt.053",
    version="1.0.0",
    lifespan=lifespan,
    docs_url="/api-docs",
    redoc_url="/api-redoc",
)

app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

_legacy_hosts = {h.strip().lower() for h in settings.REDIRECT_LEGACY_HOSTS.split(",") if h.strip()}

if settings.PRIMARY_HOST and _legacy_hosts:
    @app.middleware("http")
    async def redirect_legacy_domain(request: Request, call_next):
        host = request.headers.get("host", "").split(":")[0].lower()
        if host in _legacy_hosts and not request.url.path.startswith("/api/"):
            target = request.url.replace(scheme="https", netloc=settings.PRIMARY_HOST)
            return RedirectResponse(url=str(target), status_code=status.HTTP_301_MOVED_PERMANENTLY)
        return await call_next(request)

# CORS
origins = ["*"] if settings.ENVIRONMENT == "development" else []
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

PREFIX = f"/api/{settings.API_VERSION}"
app.include_router(health.router, prefix=PREFIX)
app.include_router(auth.router, prefix=PREFIX)
app.include_router(convert.router, prefix=PREFIX)
app.include_router(admin.router, prefix=PREFIX)
app.include_router(contact.router, prefix=PREFIX)
app.include_router(account.router, prefix=PREFIX)
app.include_router(playground.router, prefix=PREFIX)
app.include_router(reconciliation.router, prefix=PREFIX)


@app.get("/", include_in_schema=False)
async def landing():
    return FileResponse(FRONTEND_DIR / "landing.html")


@app.get("/console", include_in_schema=False)
async def console():
    return FileResponse(FRONTEND_DIR / "index.html")


@app.get("/prueba", include_in_schema=False)
async def prueba():
    return FileResponse(FRONTEND_DIR / "prueba.html")


@app.get("/ayuda", include_in_schema=False)
async def ayuda():
    return FileResponse(FRONTEND_DIR / "ayuda.html")


@app.get("/terminos", include_in_schema=False)
async def terminos():
    return FileResponse(FRONTEND_DIR / "terminos.html")


@app.get("/cuenta", include_in_schema=False)
async def cuenta():
    return FileResponse(FRONTEND_DIR / "cuenta.html")


@app.get("/playground", include_in_schema=False)
async def playground_page():
    return FileResponse(FRONTEND_DIR / "playground.html")


app.mount("/ejemplos", StaticFiles(directory=FRONTEND_DIR / "examples"), name="ejemplos")


@app.get("/robots.txt", include_in_schema=False)
async def robots(request: Request):
    base = str(request.base_url).rstrip("/")
    body = (
        "User-agent: *\n"
        "Allow: /\n"
        "Disallow: /console\n"
        "Disallow: /cuenta\n"
        "Disallow: /api/\n"
        f"Sitemap: {base}/sitemap.xml\n"
    )
    return PlainTextResponse(body)


@app.get("/sitemap.xml", include_in_schema=False)
async def sitemap(request: Request):
    base = str(request.base_url).rstrip("/")
    urls = [
        (f"{base}/", "1.0"),
        (f"{base}/playground", "0.9"),
        (f"{base}/ayuda", "0.7"),
        (f"{base}/prueba", "0.5"),
        (f"{base}/terminos", "0.3"),
    ]
    entries = "".join(
        f"<url><loc>{loc}</loc><priority>{priority}</priority></url>"
        for loc, priority in urls
    )
    body = (
        '<?xml version="1.0" encoding="UTF-8"?>'
        '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
        f"{entries}"
        "</urlset>"
    )
    return Response(content=body, media_type="application/xml")


@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
    logger.error(f"[{request_id}] Unhandled error: {exc}", exc_info=True)
    detail = str(exc) if settings.ENVIRONMENT == "development" else "Ocurrió un error inesperado."
    return JSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content={
            "error": "Internal Server Error",
            "detail": detail,
            "request_id": request_id,
        },
    )
