"""S1-S4: API & Config checks."""

import json
import os
import sys

from recoil_checks import register_check


def _resolve_pipeline_config_path(base):
    """Locate pipeline_config.json — canonical at recoil/config/pipeline_config.json."""
    # Try core.paths.CONFIG_PATH (canonical SSOT)
    try:
        # base = .../recoil/pipeline → parent = .../recoil
        recoil_root = os.path.dirname(os.path.abspath(base))
        if recoil_root not in sys.path:
            sys.path.insert(0, recoil_root)
        from recoil.core.paths import CONFIG_PATH
        return str(CONFIG_PATH)
    except Exception:
        # Fallback: derive from base
        recoil_root = os.path.dirname(os.path.abspath(base))
        return os.path.join(recoil_root, "config", "pipeline_config.json")


def check_model_profiles(base, discovered):
    """S1: model_profiles.json is valid JSON with required fields."""
    passes, fails, warns = [], [], []
    # model_profiles.json lives in recoil/config (parent of pipeline base)
    recoil_root = os.path.dirname(os.path.abspath(base))
    path = os.path.join(recoil_root, "config", "model_profiles.json")

    if not os.path.isfile(path):
        fails.append("model_profiles.json not found")
        return {"pass": passes, "fail": fails, "warn": warns}

    try:
        with open(path) as f:
            data = json.load(f)
    except json.JSONDecodeError as e:
        fails.append(f"model_profiles.json invalid JSON: {e}")
        return {"pass": passes, "fail": fails, "warn": warns}

    required_fields = {"provider", "modality"}
    for model_id, profile in data.items():
        if model_id == "schema_version":
            continue
        if not isinstance(profile, dict):
            continue
        missing = required_fields - set(profile.keys())
        if missing:
            fails.append(f"{model_id}: missing fields {missing}")
        else:
            passes.append(f"{model_id}: has required fields")

        # Check cost field exists (various naming)
        has_cost = any(k.startswith("cost_per") for k in profile)
        if not has_cost:
            warns.append(f"{model_id}: no cost_per_* field")

    return {"pass": passes, "fail": fails, "warn": warns}


def check_pipeline_config(base, discovered):
    """S2: pipeline_config.json is valid and paths resolve."""
    passes, fails, warns = [], [], []
    path = _resolve_pipeline_config_path(base)

    if not os.path.isfile(path):
        fails.append("pipeline_config.json not found")
        return {"pass": passes, "fail": fails, "warn": warns}

    try:
        with open(path) as f:
            data = json.load(f)
    except json.JSONDecodeError as e:
        fails.append(f"pipeline_config.json invalid JSON: {e}")
        return {"pass": passes, "fail": fails, "warn": warns}

    passes.append("pipeline_config.json valid JSON")

    # Check that key paths exist
    for key in ("projects_root", "recoil_engine_root"):
        val = data.get(key, "")
        if val:
            expanded = os.path.expanduser(val)
            if os.path.isdir(expanded):
                passes.append(f"{key} ({val}) exists")
            else:
                warns.append(f"{key} ({val}) directory not found")
        else:
            warns.append(f"{key} not set in config")

    # Check default_project (optional in pipeline_config)
    if data.get("default_project"):
        passes.append(f"default_project: {data['default_project']}")
    else:
        warns.append("default_project not set")

    return {"pass": passes, "fail": fails, "warn": warns}


def check_env_api_keys(base, discovered):
    """S3: Required API env vars are set (don't leak values)."""
    passes, fails, warns = [], [], []

    env_keys = [
        ("GOOGLE_API_KEY", True),
        ("FAL_KEY", False),
        ("KLING_API_KEY", False),
    ]

    for key, required in env_keys:
        val = os.environ.get(key, "")
        if val:
            passes.append(f"{key} is set ({len(val)} chars)")
        elif required:
            fails.append(f"{key} not set (required)")
        else:
            warns.append(f"{key} not set (optional)")

    return {"pass": passes, "fail": fails, "warn": warns}


def check_config_model_refs(base, discovered):
    """S4: Models referenced in pipeline_config exist in model_profiles."""
    passes, fails, warns = [], [], []
    config_path = _resolve_pipeline_config_path(base)
    recoil_root = os.path.dirname(os.path.abspath(base))
    profiles_path = os.path.join(recoil_root, "config", "model_profiles.json")

    if not os.path.isfile(config_path) or not os.path.isfile(profiles_path):
        warns.append("Cannot cross-check — config or profiles missing")
        return {"pass": passes, "fail": fails, "warn": warns}

    try:
        with open(config_path) as f:
            config = json.load(f)
        with open(profiles_path) as f:
            profiles = json.load(f)
    except json.JSONDecodeError:
        warns.append("Cannot cross-check — JSON parse error")
        return {"pass": passes, "fail": fails, "warn": warns}

    profile_ids = {k for k in profiles.keys() if k != "schema_version"}

    # Check default_model
    for key in ("default_model", "exploration_model", "fallback_exploration_model"):
        model = config.get(key)
        if model:
            if model in profile_ids:
                passes.append(f"config.{key} ({model}) in model_profiles")
            else:
                fails.append(f"config.{key} ({model}) NOT in model_profiles")

    # Check routing models
    routing = config.get("routing", {}).get("models", {})
    for route_key, model in routing.items():
        if model in profile_ids:
            passes.append(f"routing.{route_key} ({model}) in model_profiles")
        else:
            fails.append(f"routing.{route_key} ({model}) NOT in model_profiles")

    return {"pass": passes, "fail": fails, "warn": warns}


register_check("s1_model_profiles", "Model Profiles JSON", check_model_profiles, section="api", quick=True)
register_check("s2_pipeline_config", "Pipeline Config Paths", check_pipeline_config, section="api", quick=True)
register_check("s3_env_api_keys", "API Environment Variables", check_env_api_keys, section="api")
register_check("s4_config_model_refs", "Config ↔ Model Profiles Sync", check_config_model_refs, section="api", quick=True)
