"""
FastAPI microservice that wraps `create_docx_report()` for use by n8n.

Endpoints:
- GET  /health          liveness probe
- POST /generate        accept the `Report: Build Payload` JSON and return a DOCX

Run locally:
    uvicorn report_service.main:app --host 0.0.0.0 --port 8000
"""
from __future__ import annotations

import logging
import os
import tempfile
from contextlib import contextmanager
from typing import Any

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse, Response

from src.reporting import docx as docx_module
from src.reporting.docx import create_docx_report
from src.reporting.filename_utils import slugify_ascii_underscore

from report_service.adapter import apply_farm_config, build_dataframes

logging.basicConfig(
    level=os.getenv("LOG_LEVEL", "INFO"),
    format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logger = logging.getLogger("report_service")

app = FastAPI(title="Lightning Report Service", version="1.0.0")

DOCX_MIME = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"


@contextmanager
def _override_gemini_commentary(override_text: str | None):
    """
    If n8n already called Gemini and forwarded the text, short-circuit
    `generate_gemini_paragraph` so the downstream report uses it verbatim.

    Restores the original function on exit even if the request fails.
    """
    if not override_text:
        yield
        return

    original = docx_module.generate_gemini_paragraph
    docx_module.generate_gemini_paragraph = lambda _ctx, api_key=None: override_text
    try:
        yield
    finally:
        docx_module.generate_gemini_paragraph = original


def _build_filename(payload: dict[str, Any]) -> str:
    safe_name = slugify_ascii_underscore(payload.get("customer_name") or "report")
    from src.config import config

    start = (config.analysis_start_date or "").replace(" ", "_").replace(":", "").replace("-", "")
    end = (config.analysis_end_date or "").replace(" ", "_").replace(":", "").replace("-", "")
    parts = [safe_name]
    if start:
        parts.append(start)
    if end:
        parts.append(end)
    parts.append("report.docx")
    return "_".join(parts)


@app.get("/health")
def health() -> JSONResponse:
    return JSONResponse({"ok": True, "service": "lightning-report", "version": app.version})


@app.post("/generate")
async def generate(request: Request) -> Response:
    try:
        payload: dict[str, Any] = await request.json()
    except Exception as exc:
        raise HTTPException(status_code=400, detail=f"Invalid JSON body: {exc}") from exc

    if not isinstance(payload, dict):
        raise HTTPException(status_code=400, detail="Request body must be a JSON object")

    customer_name = payload.get("customer_name") or "<unknown>"
    n_strikes = int(payload.get("n_strikes") or 0)
    logger.info(
        "Generating report for customer=%s n_strikes=%s n_turbines=%s",
        customer_name,
        n_strikes,
        len(payload.get("turbines") or []),
    )

    try:
        apply_farm_config(payload)
        turbine_df, lightning_df = build_dataframes(payload)
    except ValueError as exc:
        logger.warning("Payload validation failed: %s", exc)
        raise HTTPException(status_code=422, detail=str(exc)) from exc

    storm_records = payload.get("storm_records") or None
    filename = _build_filename(payload)

    tmp_fd, tmp_path = tempfile.mkstemp(suffix=".docx")
    os.close(tmp_fd)

    try:
        with _override_gemini_commentary(payload.get("gemini_text")):
            create_docx_report(
                tmp_path,
                turbine_df,
                lightning_df,
                storm_data_path=None,
                storm_data_records=storm_records,
            )
        with open(tmp_path, "rb") as fh:
            data = fh.read()
    except Exception as exc:
        logger.exception("Report generation failed for %s", customer_name)
        raise HTTPException(status_code=500, detail=f"Report generation failed: {exc}") from exc
    finally:
        try:
            os.unlink(tmp_path)
        except OSError:
            pass

    logger.info("Generated %s (%d bytes) for %s", filename, len(data), customer_name)
    return Response(
        content=data,
        media_type=DOCX_MIME,
        headers={
            "Content-Disposition": f'attachment; filename="{filename}"',
            "X-Report-Filename": filename,
            "X-Report-Customer": str(customer_name),
            "X-Report-Strikes": str(n_strikes),
        },
    )
