import math
from pathlib import Path
from typing import Dict, Any


def analyze_file_metrics(path) -> Dict[str, Any]:
    """Analyze a single file and return metrics dict.

    Returns:
        {"file": str(path), "name": filename, "avg_cc": float, "max_cc": int,
         "func_count": int, "mi": float, "language": str}
    """
    p = Path(path)
    # lazy import lizard to avoid hard dependency until needed
    try:
        import lizard as lizard_mod
    except Exception:
        lizard_mod = None

    # If lizard is not available, attempt to approximate with simple counts
    if lizard_mod is None:
        # fallback: minimal values using line counts
        loc = 0
        try:
            with p.open('r', encoding='utf-8', errors='ignore') as fh:
                loc = sum(1 for _ in fh)
        except Exception:
            loc = 0
        return {
            "file": str(p),
            "name": p.name,
            "avg_cc": 0.0,
            "max_cc": 0,
            "func_count": 0,
            "mi": 0.0,
            "language": "unknown",
        }

    # use lizard when available
    res = lizard_mod.analyze_file(str(p))
    funcs = res.function_list if hasattr(res, 'function_list') else []
    cc_values = [getattr(f, 'cyclomatic_complexity', 0) for f in funcs]
    func_count = len(cc_values)
    avg_cc = float(sum(cc_values) / func_count) if func_count else 0.0
    max_cc = int(max(cc_values)) if cc_values else 0

    # Maintainability Index (approximate): use Coleman-Oman formula when possible.
    # MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln(LOC)
    loc = getattr(res, 'nloc', None) or 0
    if not loc:
        try:
            with p.open('r', encoding='utf-8', errors='ignore') as fh:
                loc = sum(1 for _ in fh)
        except Exception:
            loc = 0
    hv = None
    try:
        hv = getattr(res, 'halstead_volume', None)
    except Exception:
        hv = None

    mi_raw = 171.0
    try:
        if hv and hv > 0 and loc and loc > 0:
            mi_raw = 171 - 5.2 * math.log(max(1.0, hv)) - 0.23 * avg_cc - 16.2 * math.log(max(1.0, loc))
        elif loc and loc > 0:
            mi_raw = 171 - 0.23 * avg_cc - 16.2 * math.log(max(1.0, loc))
        else:
            mi_raw = 0.0
        mi = max(0.0, min(100.0, (mi_raw * 100.0 / 171.0)))
    except Exception:
        mi = 0.0

    # attempt to map extension to language
    ext = p.suffix
    language = ext.lower().lstrip('.') if ext else 'unknown'
    return {
        "file": str(p),
        "name": p.name,
        "avg_cc": round(avg_cc, 2),
        "max_cc": int(max_cc),
        "func_count": int(func_count),
        "mi": round(mi, 2),
        "language": language,
    }
