from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict, List, Tuple

PRESET_FILES: Dict[str, str] = {
    "jsonl_sm": "jsonl_to_jsonl",
    "simple_sm": "jsonl_to_api",
}


def _run_profiles_dir() -> Path:
    return Path(__file__).resolve().parents[2] / "run_profiles"


def _preset_templates_dir() -> Path:
    return _run_profiles_dir() / "preset"


def _replace_placeholders(value: Any, project_root: Path) -> Any:
    if isinstance(value, str):
        return value.replace("${PROJECT_ROOT}", str(project_root))
    if isinstance(value, dict):
        return {k: _replace_placeholders(v, project_root) for k, v in value.items()}
    if isinstance(value, list):
        return [_replace_placeholders(v, project_root) for v in value]
    return value


def list_preset_names() -> List[str]:
    return sorted(PRESET_FILES.keys())


def get_preset_file_candidates(preset_name: str) -> List[Path]:
    if preset_name not in PRESET_FILES:
        raise ValueError(f"Unknown preset: {preset_name}. Available: {list_preset_names()}")

    base = PRESET_FILES[preset_name]
    run_profiles_root = _run_profiles_dir()
    preset_templates_root = _preset_templates_dir()
    return [
        run_profiles_root / f"{base}.local.yaml",
        run_profiles_root / f"{base}.local.yml",
        run_profiles_root / f"{base}.local.json",
        preset_templates_root / f"{base}.default.yaml",
        preset_templates_root / f"{base}.default.yml",
        preset_templates_root / f"{base}.default.json",
    ]


def resolve_preset_file(preset_name: str) -> Tuple[Path, bool]:
    candidates = get_preset_file_candidates(preset_name)
    for idx, path in enumerate(candidates):
        if path.exists() and path.is_file():
            return path, idx > 0
    raise FileNotFoundError(
        f"No preset file found for {preset_name}. Tried: {[str(p) for p in candidates]}"
    )


def load_overrides_from_file(file_path: Path, project_root: Path) -> Dict[str, Any]:
    suffix = file_path.suffix.lower()
    text = file_path.read_text(encoding="utf-8")

    if suffix in {".yaml", ".yml"}:
        try:
            import yaml  # type: ignore
        except Exception as exc:
            raise RuntimeError(
                "YAML config requires PyYAML. Install with: pip install pyyaml"
            ) from exc
        payload = yaml.safe_load(text)
    else:
        payload = json.loads(text)

    resolved = _replace_placeholders(payload, project_root)
    if not isinstance(resolved, dict):
        raise ValueError(f"Preset file must contain object mapping: {file_path}")
    resolved.pop("extensions", None)
    return resolved


def load_named_preset_overrides(project_root: Path, preset_name: str) -> Tuple[Dict[str, Any], Path, bool]:
    file_path, used_default = resolve_preset_file(preset_name)
    overrides = load_overrides_from_file(file_path, project_root)
    return overrides, file_path, used_default
