#!/usr/bin/env python3
"""Fair Lending Compliance Audit — Reference Implementation.

Causal fairness analysis: decompose the effect of protected attributes
into direct (concerning) and indirect (legitimate) causal pathways.
Audit individual decisions for ECOA/CFPB compliance.

Usage:
    python -m examples.fair_lending_audit
    # or
    python examples/fair_lending_audit.py
"""

from __future__ import annotations

import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))

from orxaq.credit.fair_lending import (
    LEGITIMATE_MEDIATORS,
    PROTECTED_CHARACTERISTICS,
    FairLendingAnalyzer,
    FairnessReport,
)
from orxaq.credit.ontology import build_credit_ontology
from orxaq.credit.synthetic import CreditDataGenerator
from orxaq.kernel import WorldDAG


def setup() -> tuple[WorldDAG, list[dict]]:
    """Build ontology and generate synthetic portfolio."""
    dag = build_credit_ontology()
    gen = CreditDataGenerator(dag, seed=42)
    data = gen.generate(500)
    return dag, data


def effect_decomposition(dag: WorldDAG) -> None:
    """Decompose effect of age on default into causal pathways."""
    analyzer = FairLendingAnalyzer(dag)
    decomp = analyzer.decompose_effect("age", "default_flag")

    print(f"{'='*60}")
    print("CAUSAL EFFECT DECOMPOSITION")
    print(f"{'='*60}")
    print(f"  Protected attribute: {decomp.protected_var}")
    print(f"  Outcome:             {decomp.outcome_var}")
    print(f"  Total effect:        {decomp.total_effect:.4f}")
    print(f"  Direct effect:       {decomp.direct_effect:.4f}")

    if decomp.indirect_effects:
        print("\n  Indirect Effects (through mediators):")
        print(f"  {'Mediator':<25} {'Effect':>10}")
        print(f"  {'-'*25} {'-'*10}")
        for mediator, effect in sorted(
            decomp.indirect_effects.items(), key=lambda x: abs(x[1]), reverse=True
        ):
            legitimacy = "legitimate" if mediator in LEGITIMATE_MEDIATORS else "CONCERNING"
            print(f"  {mediator:<25} {effect:>10.4f}  [{legitimacy}]")

    print(f"\n  Legitimate paths:  {len(decomp.legitimate_paths)}")
    for path in decomp.legitimate_paths:
        print(f"    {' → '.join(path)}")

    print(f"  Concerning paths:  {len(decomp.concerning_paths)}")
    for path in decomp.concerning_paths:
        print(f"    {' → '.join(path)}")


def audit_borrowers(dag: WorldDAG, data: list[dict]) -> list[FairnessReport]:
    """Audit individual borrower decisions for fairness."""
    analyzer = FairLendingAnalyzer(dag)

    print(f"\n{'='*60}")
    print("INDIVIDUAL BORROWER AUDIT")
    print(f"{'='*60}")

    # Audit a sample of borrowers
    sample = data[:10]
    reports: list[FairnessReport] = []

    print(
        f"  {'#':<4} {'Age':>5} {'Decision':<10} {'CF Decision':<12} " f"{'Changed':>8} {'Rec':<8}"
    )
    print(f"  {'-'*4} {'-'*5} {'-'*10} {'-'*12} {'-'*8} {'-'*8}")

    for i, borrower in enumerate(sample):
        report = analyzer.audit_decision(borrower)
        reports.append(report)
        changed_marker = "YES" if report.decision_changed else "no"
        print(
            f"  {i+1:<4} {borrower.get('age', 0):>5.0f} {report.decision:<10} "
            f"{report.counterfactual_decision:<12} {changed_marker:>8} "
            f"{report.recommendation:<8}"
        )

    return reports


def portfolio_summary(dag: WorldDAG, data: list[dict]) -> dict:
    """Aggregate fairness metrics across the entire portfolio."""
    analyzer = FairLendingAnalyzer(dag)

    total = len(data)
    flagged = 0
    review = 0
    clear = 0
    changed = 0

    for borrower in data:
        report = analyzer.audit_decision(borrower)
        if report.recommendation == "flag":
            flagged += 1
        elif report.recommendation == "review":
            review += 1
        else:
            clear += 1
        if report.decision_changed:
            changed += 1

    summary = {
        "total_audited": total,
        "flagged": flagged,
        "flagged_rate": round(flagged / total, 4) if total else 0.0,
        "review": review,
        "review_rate": round(review / total, 4) if total else 0.0,
        "clear": clear,
        "clear_rate": round(clear / total, 4) if total else 0.0,
        "decisions_changed": changed,
        "change_rate": round(changed / total, 4) if total else 0.0,
    }

    print(f"\n{'='*60}")
    print("PORTFOLIO FAIRNESS SUMMARY")
    print(f"{'='*60}")
    print(f"  Total borrowers audited: {total}")
    print(f"  Flagged:                 {flagged} ({summary['flagged_rate']:.1%})")
    print(f"  Needs review:            {review} ({summary['review_rate']:.1%})")
    print(f"  Clear:                   {clear} ({summary['clear_rate']:.1%})")
    print(f"  Decisions changed:       {changed} ({summary['change_rate']:.1%})")

    return summary


def export_json(summary: dict) -> str:
    """Export portfolio fairness summary as JSON."""
    return json.dumps(summary, indent=2)


def main() -> None:
    """Run the full fair lending audit pipeline."""
    # 1. Setup
    dag, data = setup()
    print(f"Portfolio: {len(data)} loans")
    print(f"Protected characteristics: {sorted(PROTECTED_CHARACTERISTICS)}")
    print(f"Legitimate mediators: {sorted(LEGITIMATE_MEDIATORS)}")

    # 2. Effect decomposition
    effect_decomposition(dag)

    # 3. Audit individual borrowers
    audit_borrowers(dag, data)

    # 4. Portfolio summary
    summary = portfolio_summary(dag, data)

    # 5. JSON export
    print(f"\n{'='*60}")
    print("JSON OUTPUT")
    print(f"{'='*60}")
    print(export_json(summary))


if __name__ == "__main__":
    main()
