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

from scripts.mindmodel import loader
from scripts.mindmodel import checks


def validate_manifest(path: str, base_dir: str = None) -> Tuple[int, Dict[str, Any]]:
    """Validate a manifest file at `path`.

    Returns a tuple (exit_code, report).

    exit codes:
      0 - ok (no issues)
      1 - warnings (only truncated snippets found)
      2 - critical (missing files, secrets, or parse error)
    """
    report: Dict[str, Any] = {
        "path": path,
        "secrets": [],
        "missing_files": [],
        "truncated": 0,
        "constraints": [],
    }

    p = Path(path)
    try:
        raw_text = p.read_text(encoding="utf-8")
    except Exception as exc:
        report["load_error"] = f"Manifest file not readable: {exc}"
        return 2, report

    # scan for secrets in the manifest text
    secrets = checks.find_potential_secrets(raw_text)
    report["secrets"] = secrets

    try:
        manifest = loader.load_manifest(path)
    except loader.ManifestLoadError as exc:
        report["load_error"] = str(exc)
        # treat parse/load errors as critical
        return 2, report

    constraints = manifest.get("constraints") or []

    for constraint in constraints:
        c_rep: Dict[str, Any] = {"constraint": constraint, "evidence": []}
        for ev in (
            constraint.get("evidence", [])
            if isinstance(constraint.get("evidence", []), list)
            else []
        ):
            text = ev.get("text") if isinstance(ev, dict) else None
            file_ref = ev.get("file") if isinstance(ev, dict) else None

            exists = True
            if file_ref:
                if not checks.file_exists(base_dir or "", file_ref):
                    exists = False
                    report["missing_files"].append(file_ref)

            truncated = False
            if text:
                truncated = checks.detect_truncated(text)
                if truncated:
                    report["truncated"] += 1

            c_rep["evidence"].append(
                {
                    "text": text,
                    "file": file_ref,
                    "exists": exists,
                    "truncated": truncated,
                }
            )

        report["constraints"].append(c_rep)

    # decide exit code
    if report["secrets"]:
        return 2, report

    if report["missing_files"]:
        return 2, report

    if report["truncated"] > 0:
        return 1, report

    return 0, report


def main(argv: List[str]) -> int:
    import sys

    if len(argv) < 2:
        print(json.dumps({"error": "manifest path required"}))
        return 2

    path = argv[1]
    base_dir = argv[2] if len(argv) > 2 else None

    code, report = validate_manifest(path, base_dir=base_dir)
    print(json.dumps(report))
    return code


# no execution at import time
