from __future__ import annotations

from fastapi import APIRouter, Request, Form, UploadFile, File
from fastapi.responses import HTMLResponse
from pathlib import Path
import os
import json
from ..app import templates
from ..services.build_utils import owned_set as owned_set_helper, owned_names as owned_names_helper
from ..services.summary_utils import summary_ctx
from ..services import orchestrator as orch


router = APIRouter(prefix="/configs")


def _config_dir() -> Path:
    # Prefer explicit env var if provided, else default to ./config
    p = os.getenv("DECK_CONFIG")
    if p:
        # If env points to a file, use its parent dir; else treat as dir
        pp = Path(p)
        return (pp.parent if pp.suffix else pp).resolve()
    return (Path.cwd() / "config").resolve()


def _list_configs() -> list[dict]:
    d = _config_dir()
    try:
        d.mkdir(parents=True, exist_ok=True)
    except Exception:
        pass
    items: list[dict] = []
    for p in sorted(d.glob("*.json"), key=lambda x: x.stat().st_mtime, reverse=True):
        meta = {"name": p.name, "path": str(p), "mtime": p.stat().st_mtime}
        try:
            with p.open("r", encoding="utf-8") as f:
                data = json.load(f)
            meta["commander"] = data.get("commander")
            tags = [t for t in [data.get("primary_tag"), data.get("secondary_tag"), data.get("tertiary_tag")] if t]
            meta["tags"] = tags
            meta["bracket_level"] = data.get("bracket_level")
        except Exception:
            pass
        items.append(meta)
    return items


@router.get("/", response_class=HTMLResponse)
async def configs_index(request: Request) -> HTMLResponse:
    items = _list_configs()
    # Load example deck.json from the config directory, if present
    example_json = None
    example_name = "deck.json"
    try:
        example_path = _config_dir() / example_name
        if example_path.exists() and example_path.is_file():
            example_json = example_path.read_text(encoding="utf-8")
    except Exception:
        example_json = None
    return templates.TemplateResponse(
        "configs/index.html",
        {"request": request, "items": items, "example_json": example_json, "example_name": example_name},
    )


@router.get("/view", response_class=HTMLResponse)
async def configs_view(request: Request, name: str) -> HTMLResponse:
    base = _config_dir()
    p = (base / name).resolve()
    # Safety: ensure the resolved path is within config dir
    try:
        if base not in p.parents and p != base:
            raise ValueError("Access denied")
    except Exception:
        pass
    if not (p.exists() and p.is_file() and p.suffix.lower() == ".json"):
        return templates.TemplateResponse(
            "configs/index.html",
            {"request": request, "items": _list_configs(), "error": "Config not found."},
        )
    try:
        data = json.loads(p.read_text(encoding="utf-8"))
    except Exception as e:
        return templates.TemplateResponse(
            "configs/index.html",
            {"request": request, "items": _list_configs(), "error": f"Failed to read JSON: {e}"},
        )
    return templates.TemplateResponse(
        "configs/view.html",
        {"request": request, "path": str(p), "name": p.name, "data": data},
    )


@router.post("/run", response_class=HTMLResponse)
async def configs_run(request: Request, name: str = Form(...), use_owned_only: str | None = Form(None)) -> HTMLResponse:
    base = _config_dir()
    p = (base / name).resolve()
    try:
        if base not in p.parents and p != base:
            raise ValueError("Access denied")
    except Exception:
        pass
    if not (p.exists() and p.is_file() and p.suffix.lower() == ".json"):
        return templates.TemplateResponse(
            "configs/index.html",
            {"request": request, "items": _list_configs(), "error": "Config not found."},
        )
    try:
        cfg = json.loads(p.read_text(encoding="utf-8"))
    except Exception as e:
        return templates.TemplateResponse(
            "configs/index.html",
            {"request": request, "items": _list_configs(), "error": f"Failed to read JSON: {e}"},
        )

    commander = cfg.get("commander", "")
    tags = [t for t in [cfg.get("primary_tag"), cfg.get("secondary_tag"), cfg.get("tertiary_tag")] if t]
    bracket = int(cfg.get("bracket_level") or 0)
    ideals = cfg.get("ideal_counts", {}) or {}
    # Optional combine mode for tags (AND/OR); support a few aliases
    try:
        tag_mode = (str(cfg.get("tag_mode") or cfg.get("combine_mode") or cfg.get("mode") or "AND").upper())
        if tag_mode not in ("AND", "OR"):
            tag_mode = "AND"
    except Exception:
        tag_mode = "AND"

    # Optional owned-only for headless runs via JSON flag or form override
    owned_flag = False
    try:
        uo = cfg.get("use_owned_only")
        if isinstance(uo, bool):
            owned_flag = uo
        elif isinstance(uo, str):
            owned_flag = uo.strip().lower() in ("1","true","yes","on")
    except Exception:
        owned_flag = False

    # Form override takes precedence if provided
    if use_owned_only is not None:
        owned_flag = str(use_owned_only).strip().lower() in ("1","true","yes","on")

    owned_names = owned_names_helper() if owned_flag else None

    # Optional combos preferences
    prefer_combos = False
    try:
        pc = cfg.get("prefer_combos")
        if isinstance(pc, bool):
            prefer_combos = pc
        elif isinstance(pc, str):
            prefer_combos = pc.strip().lower() in ("1","true","yes","on")
    except Exception:
        prefer_combos = False
    combo_target_count = None
    try:
        ctc = cfg.get("combo_target_count")
        if isinstance(ctc, int):
            combo_target_count = ctc
        elif isinstance(ctc, str) and ctc.strip().isdigit():
            combo_target_count = int(ctc.strip())
    except Exception:
        combo_target_count = None
    combo_balance = None
    try:
        cb = cfg.get("combo_balance")
        if isinstance(cb, str) and cb.strip().lower() in ("early","late","mix"):
            combo_balance = cb.strip().lower()
    except Exception:
        combo_balance = None

    # Run build headlessly with orchestrator
    res = orch.run_build(
        commander=commander,
        tags=tags,
        bracket=bracket,
        ideals=ideals,
        tag_mode=tag_mode,
    use_owned_only=owned_flag,
        owned_names=owned_names,
        # Thread combo prefs through staged headless run
        prefer_combos=prefer_combos,
        combo_target_count=combo_target_count,
        combo_balance=combo_balance,
    )
    if not res.get("ok"):
        return templates.TemplateResponse(
            "configs/run_result.html",
            {
                "request": request,
                "ok": False,
                "error": res.get("error") or "Build failed",
                "log": res.get("log", ""),
                "cfg_name": p.name,
                "commander": commander,
                "tag_mode": tag_mode,
                "use_owned_only": owned_flag,
                "owned_set": owned_set_helper(),
            },
        )
    ctx = {
        "request": request,
        "ok": True,
        "log": res.get("log", ""),
        "csv_path": res.get("csv_path"),
        "txt_path": res.get("txt_path"),
        "summary": res.get("summary"),
        "cfg_name": p.name,
        "commander": commander,
        "tag_mode": tag_mode,
        "use_owned_only": owned_flag,
    }
    ctx.update(summary_ctx(summary=res.get("summary"), commander=commander, tags=tags))
    return templates.TemplateResponse("configs/run_result.html", ctx)



@router.post("/upload", response_class=HTMLResponse)
async def configs_upload(request: Request, file: UploadFile = File(...)) -> HTMLResponse:
    # Optional helper: allow uploading a JSON config
    try:
        content = await file.read()
        data = json.loads(content.decode("utf-8"))
        # Minimal validation
        if not data.get("commander"):
            raise ValueError("Missing 'commander'")
    except Exception as e:
        return templates.TemplateResponse(
            "configs/index.html",
            {"request": request, "items": _list_configs(), "error": f"Invalid JSON: {e}"},
        )
    # Save to config dir with original filename (or unique)
    d = _config_dir()
    d.mkdir(parents=True, exist_ok=True)
    fname = file.filename or "config.json"
    out = d / fname
    i = 1
    while out.exists():
        stem = out.stem
        out = d / f"{stem}_{i}.json"
        i += 1
    out.write_text(json.dumps(data, indent=2), encoding="utf-8")
    return templates.TemplateResponse(
        "configs/index.html",
        {"request": request, "items": _list_configs(), "notice": f"Uploaded {out.name}"},
    )
