"""DM spec template loader — load pre-built table specs per ERP system.

Templates live in ``templates/dm_specs/<erp>.json`` and follow the
TableSpec/ColumnSpec JSON schema from ``dm_loader.py``.
"""

from __future__ import annotations

import logging
from pathlib import Path
from typing import Any, Dict, List, Optional

logger = logging.getLogger(__name__)

# Resolve project root (3 levels up from this file)
_TEMPLATES_DIR = Path(__file__).resolve().parents[3] / "templates" / "dm_specs"

# Canonical ERP ids we support with curated DM templates.
_CANONICAL_ERP_TEMPLATES = {
    "enertia",
    "wolfepak",
    "sap",
    "netsuite",
    "quickbooks",
}

# Optional shorthand aliases accepted from callers.
_ERP_ALIASES = {
    "qb": "quickbooks",
    "quick_books": "quickbooks",
    "ns": "netsuite",
    "wp": "wolfepak",
}


def list_dm_templates() -> List[Dict[str, object]]:
    """List available DM spec templates.

    Returns:
        List of dicts with erp name, path, and table count.
    """
    results = []
    if not _TEMPLATES_DIR.exists():
        return results

    for p in sorted(_TEMPLATES_DIR.glob("*.json")):
        try:
            import json
            data = json.loads(p.read_text(encoding="utf-8"))
            count = len(data) if isinstance(data, list) else 1
        except Exception:
            count = 0
        results.append({
            "erp": p.stem,
            "path": str(p),
            "table_count": count,
        })
    return results


def load_dm_template(erp_name: str) -> Optional[List]:
    """Load a DM spec template by ERP name.

    Args:
        erp_name: ERP identifier matching filename stem (e.g. 'enertia').

    Returns:
        List of TableSpec objects, or None if template not found.
    """
    from ..dm_loader import DMSpecLoader

    normalized = normalize_erp_name(erp_name)
    if not normalized:
        return None
    path = _TEMPLATES_DIR / f"{normalized}.json"
    if not path.exists():
        logger.warning("No DM template found for ERP: %s (looked at %s)", normalized, path)
        return None

    return DMSpecLoader.from_json(path)


def normalize_erp_name(erp_name: str) -> str:
    """Normalize ERP names and aliases to a canonical lower-case id."""
    value = (erp_name or "").strip().lower()
    if not value:
        return ""
    return _ERP_ALIASES.get(value, value)


def has_dm_template(erp_name: str) -> bool:
    """Return True if a DM template file exists for the ERP."""
    normalized = normalize_erp_name(erp_name)
    if not normalized:
        return False
    return (_TEMPLATES_DIR / f"{normalized}.json").exists()


def resolve_dm_template_erp(explicit_erp: str, table_names: List[str]) -> Dict[str, Any]:
    """Resolve which ERP template should be used.

    Precedence:
      1) explicit ERP (or alias) if template exists
      2) detected ERP from table names if template exists
      3) no template
    """
    explicit_norm = normalize_erp_name(explicit_erp)
    if explicit_norm and has_dm_template(explicit_norm):
        return {
            "erp_type_input": explicit_erp or "",
            "erp_type_resolved": explicit_norm,
            "template_used": True,
            "template_resolution": "explicit" if explicit_norm == (explicit_erp or "").strip().lower() else "alias",
            "detected_erp": "",
        }

    detected = ""
    if table_names:
        try:
            from .registry import detect_erp_type

            detected = normalize_erp_name(detect_erp_type(table_names) or "")
        except Exception:
            detected = ""

    if detected and has_dm_template(detected):
        return {
            "erp_type_input": explicit_erp or "",
            "erp_type_resolved": detected,
            "template_used": True,
            "template_resolution": "detected",
            "detected_erp": detected,
        }

    return {
        "erp_type_input": explicit_erp or "",
        "erp_type_resolved": explicit_norm if explicit_norm in _CANONICAL_ERP_TEMPLATES else "",
        "template_used": False,
        "template_resolution": "none",
        "detected_erp": detected,
    }
