#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
═══════════════════════════════════════════════════════════════════════════════
 ARGUS MCP — Memory Reader
 Accès en lecture à la mémoire YAML d'Argus
═══════════════════════════════════════════════════════════════════════════════
"""

from pathlib import Path
from typing import Any

import yaml

from . import data_dir


def get_memory_root() -> Path:
    """Retourne le chemin racine de la mémoire Argus."""
    return data_dir.get_data_dir()


def get_project_root() -> Path:
    """Retourne le chemin racine du projet Argus."""
    return data_dir.get_project_root()


def _load_yaml(path: Path) -> dict[str, Any] | list | None:
    """Charge un fichier YAML. Retourne None si le fichier n'existe pas."""
    if not path.exists():
        return None
    # SEC-006 — Validation que le chemin reste dans le périmètre du projet
    resolved = path.resolve()
    allowed_root = get_project_root().resolve()
    if not resolved.is_relative_to(allowed_root):
        return None
    with open(path, "r", encoding="utf-8") as f:
        return yaml.safe_load(f)


# ═══════════════════════════════════════════════════════════════════════════════
#  INDEX
# ═══════════════════════════════════════════════════════════════════════════════

def load_index() -> dict[str, Any]:
    """Charge l'index mémoire principal."""
    return _load_yaml(get_memory_root() / "_index.yaml") or {}


# ═══════════════════════════════════════════════════════════════════════════════
#  SEMANTIC MEMORY
# ═══════════════════════════════════════════════════════════════════════════════

def load_patterns() -> list[dict]:
    """Charge tous les defect patterns."""
    data = _load_yaml(get_memory_root() / "semantic" / "defect_patterns.yaml")
    return data.get("patterns", []) if data else []


def load_heuristics() -> list[dict]:
    """Charge toutes les heuristics de test."""
    data = _load_yaml(get_memory_root() / "semantic" / "testing_heuristics.yaml")
    heuristics = []
    if not data:
        return heuristics
    # Les heuristiques sont regroupées par catégorie (test_selection, prioritization, etc.)
    for key, value in data.items():
        if isinstance(value, list):
            for item in value:
                if isinstance(item, dict) and "id" in item:
                    heuristics.append(item)
    return heuristics


def load_context_profiles() -> list[dict]:
    """Charge les profils de contexte applicatif."""
    data = _load_yaml(get_memory_root() / "semantic" / "context_profiles.yaml")
    return data.get("profiles", []) if data else []


def load_technology_knowledge() -> dict[str, Any]:
    """Charge les connaissances technologiques."""
    return _load_yaml(get_memory_root() / "semantic" / "technology_knowledge.yaml") or {}


def load_istqb_knowledge() -> dict[str, Any]:
    """Charge les connaissances ISTQB."""
    return _load_yaml(get_memory_root() / "semantic" / "istqb_knowledge.yaml") or {}


# ═══════════════════════════════════════════════════════════════════════════════
#  EPISODIC MEMORY
# ═══════════════════════════════════════════════════════════════════════════════

def _load_episodic_dir(subdir: str) -> list[dict]:
    """Charge tous les fichiers YAML d'un sous-dossier épisodique (hors templates)."""
    directory = get_memory_root() / "episodic" / subdir
    if not directory.exists():
        return []
    entries = []
    for f in sorted(directory.glob("*.yaml")):
        if f.name.startswith("_template"):
            continue
        data = _load_yaml(f)
        if data:
            entries.append(data)
    return entries


def load_analyses() -> list[dict]:
    """Charge toutes les analyses épisodiques."""
    return _load_episodic_dir("analyses")


def load_decisions() -> list[dict]:
    """Charge toutes les décisions."""
    return _load_episodic_dir("decisions")


def load_incidents() -> list[dict]:
    """Charge tous les incidents."""
    return _load_episodic_dir("incidents")


def load_executions() -> list[dict]:
    """Charge toutes les exécutions de tests."""
    return _load_episodic_dir("executions")


# ═══════════════════════════════════════════════════════════════════════════════
#  PROJECT MEMORY
# ═══════════════════════════════════════════════════════════════════════════════

def load_projects() -> list[dict]:
    """Charge tous les profils projet (hors templates)."""
    directory = get_memory_root() / "projects"
    if not directory.exists():
        return []
    projects = []
    for f in sorted(directory.glob("*.yaml")):
        if f.name.startswith("_template"):
            continue
        data = _load_yaml(f)
        if data:
            projects.append(data)
    return projects


# ═══════════════════════════════════════════════════════════════════════════════
#  RELATIONAL MEMORY
# ═══════════════════════════════════════════════════════════════════════════════

def load_associations() -> dict[str, Any]:
    """Charge le graphe d'associations."""
    return _load_yaml(get_memory_root() / "relational" / "associations.yaml") or {}


# ═══════════════════════════════════════════════════════════════════════════════
#  PERSONA
# ═══════════════════════════════════════════════════════════════════════════════

def load_persona() -> dict[str, Any]:
    """Charge la persona Argus."""
    return _load_yaml(get_project_root() / "argus.persona.yaml") or {}


# ═══════════════════════════════════════════════════════════════════════════════
#  SEARCH UTILITIES
# ═══════════════════════════════════════════════════════════════════════════════

def search_patterns(
    query: str | None = None,
    category: str | None = None,
    min_confidence: float | None = None,
) -> list[dict]:
    """Recherche des patterns par texte, catégorie, ou seuil de confidence."""
    patterns = load_patterns()
    results = patterns

    if category:
        results = [p for p in results if p.get("category") == category]

    if min_confidence is not None:
        results = [p for p in results if p.get("confidence", 0) >= min_confidence]

    if query:
        q = query.lower()
        results = [
            p for p in results
            if q in p.get("name", "").lower()
            or q in p.get("id", "").lower()
            or q in str(p.get("signature", {}).get("description", "")).lower()
            or q in p.get("category", "").lower()
        ]

    return results


def search_heuristics(
    query: str | None = None,
    category: str | None = None,
    min_confidence: float | None = None,
) -> list[dict]:
    """Recherche des heuristics par texte, catégorie, ou seuil de confidence."""
    heuristics = load_heuristics()
    results = heuristics

    if category:
        results = [h for h in results if h.get("category") == category]

    if min_confidence is not None:
        results = [h for h in results if h.get("confidence", 0) >= min_confidence]

    if query:
        q = query.lower()
        results = [
            h for h in results
            if q in h.get("name", "").lower()
            or q in h.get("id", "").lower()
            or q in str(h.get("condition", "")).lower()
            or q in str(h.get("action", "")).lower()
            or q in h.get("category", "").lower()
        ]

    return results


def get_memory_stats() -> dict[str, Any]:
    """Retourne un résumé statistique de la mémoire."""
    index = load_index()
    patterns = load_patterns()
    heuristics = load_heuristics()

    return {
        "version": index.get("version"),
        "last_updated": index.get("last_updated"),
        "counts": {
            "patterns": len(patterns),
            "heuristics": len(heuristics),
            "analyses": index.get("episodic", {}).get("analyses", {}).get("count", 0),
            "decisions": index.get("episodic", {}).get("decisions", {}).get("count", 0),
            "incidents": index.get("episodic", {}).get("incidents", {}).get("count", 0),
            "executions": index.get("episodic", {}).get("executions", {}).get("count", 0),
        },
        "pattern_categories": list({p.get("category") for p in patterns if p.get("category")}),
        "avg_pattern_confidence": (
            round(sum(p.get("confidence", 0) for p in patterns) / len(patterns), 3)
            if patterns else 0
        ),
        "avg_heuristic_confidence": (
            round(sum(h.get("confidence", 0) for h in heuristics) / len(heuristics), 3)
            if heuristics else 0
        ),
    }
