"""本地演示/测试素材：供控制台一键预填需求与上传文件。

目录默认：仓库 test/（可用 DEMO_FIXTURES_DIR 覆盖）。
"""
from __future__ import annotations

import mimetypes
import os
from pathlib import Path

from fastapi import HTTPException
from fastapi.responses import FileResponse

_ROOT = Path(__file__).resolve().parents[1]


def fixtures_root() -> Path:
    raw = (os.getenv("DEMO_FIXTURES_DIR") or "").strip()
    if raw:
        return Path(raw).expanduser().resolve()
    return (_ROOT / "test").resolve()


# 默认演示包：沉降观测（行业示例，仅测试用）
DEFAULT_PACK = {
    "id": "settlement_demo",
    "label": "沉降观测演示包（test/）",
    "prompt": "prompts/prompt_1.txt",
    "data": "data/settlement.xlsx",
    "images": ["refs/board_a.png", "refs/board_b.png"],
    "layouts": ["refs/dashboard.html", "refs/nav.html"],
    "slug": "settlement_observation_system",
}


def _safe_file(rel: str) -> Path:
    root = fixtures_root()
    rel = (rel or "").replace("\\", "/").lstrip("/")
    if not rel or ".." in rel.split("/"):
        raise HTTPException(400, "非法路径")
    path = (root / rel).resolve()
    try:
        path.relative_to(root)
    except ValueError as e:
        raise HTTPException(400, "越界路径") from e
    if not path.is_file():
        raise HTTPException(404, f"文件不存在: {rel}")
    return path


def fixtures_manifest() -> dict:
    root = fixtures_root()
    pack = dict(DEFAULT_PACK)
    pack["root"] = str(root)
    pack["available"] = root.is_dir()

    def ok(rel: str) -> bool:
        try:
            return _safe_file(rel).is_file()
        except HTTPException:
            return False

    pack["files"] = {
        "prompt": {"path": pack["prompt"], "ok": ok(pack["prompt"])},
        "data": {"path": pack["data"], "ok": ok(pack["data"])},
        "images": [{"path": p, "ok": ok(p)} for p in pack["images"]],
        "layouts": [{"path": p, "ok": ok(p)} for p in pack["layouts"]],
    }
    return pack


def read_prompt_text() -> str:
    return _safe_file(DEFAULT_PACK["prompt"]).read_text(encoding="utf-8")


def file_response(rel: str) -> FileResponse:
    path = _safe_file(rel)
    ctype, _ = mimetypes.guess_type(str(path))
    return FileResponse(
        path,
        media_type=ctype or "application/octet-stream",
        filename=path.name,
    )
