#!/usr/bin/env python3
"""
monthly_audit.py — Wizard Council Monthly Environment Audit

Runs all three checks (bootstrap, skills audit, dependency check) and
produces a combined Markdown report. Designed to be invoked by cron or
manually.

Usage:
    python wizard-bootstrap/monthly_audit.py
    python wizard-bootstrap/monthly_audit.py --output /path/to/report.md
    python wizard-bootstrap/monthly_audit.py --post-telegram   # post to configured channel

The report is also written to ~/.hermes/wizard-council/audit-YYYY-MM.md
"""

import argparse
import io
import json
import os
import sys
from contextlib import redirect_stdout
from datetime import datetime, timezone
from pathlib import Path

# Ensure repo root is importable
_REPO_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(_REPO_ROOT))

from wizard_bootstrap import run_all_checks
from skills_audit import run_audit
from dependency_checker import run_dep_check


# ---------------------------------------------------------------------------
# Report builder
# ---------------------------------------------------------------------------

def _emoji(ok: bool) -> str:
    return "✅" if ok else "❌"


def build_report(repo_root: Path) -> str:
    now = datetime.now(timezone.utc)
    lines = [
        f"# Wizard Council Environment Audit",
        f"",
        f"**Date:** {now.strftime('%Y-%m-%d %H:%M UTC')}",
        f"",
        f"---",
        f"",
    ]

    # 1. Bootstrap checks
    lines.append("## 1. Environment Bootstrap")
    lines.append("")
    bootstrap = run_all_checks()
    for check in bootstrap.checks:
        icon = _emoji(check.passed)
        label = check.name.replace("_", " ").title()
        lines.append(f"- {icon} **{label}**: {check.message}")
        if not check.passed and check.fix_hint:
            lines.append(f"  - _Fix_: {check.fix_hint}")
    lines.append("")
    if bootstrap.passed:
        lines.append("**Environment: READY** ✅")
    else:
        failed = len(bootstrap.failed)
        lines.append(f"**Environment: {failed} check(s) FAILED** ❌")
    lines.append("")
    lines.append("---")
    lines.append("")

    # 2. Skills audit
    lines.append("## 2. Skills Drift Audit")
    lines.append("")
    skills_report = run_audit(repo_root)
    missing = skills_report.by_status("MISSING")
    extra = skills_report.by_status("EXTRA")
    outdated = skills_report.by_status("OUTDATED")
    ok_count = len(skills_report.by_status("OK"))
    total = len(skills_report.drifts)

    lines.append(f"| Status | Count |")
    lines.append(f"|--------|-------|")
    lines.append(f"| ✅ OK | {ok_count} |")
    lines.append(f"| ❌ Missing | {len(missing)} |")
    lines.append(f"| ⚠️ Extra | {len(extra)} |")
    lines.append(f"| 🔄 Outdated | {len(outdated)} |")
    lines.append(f"| **Total** | **{total}** |")
    lines.append("")

    if missing:
        lines.append("### Missing Skills (in repo, not installed)")
        for d in missing:
            lines.append(f"- `{d.skill_path}`")
        lines.append("")

    if outdated:
        lines.append("### Outdated Skills")
        for d in outdated:
            lines.append(f"- `{d.skill_path}` (repo: `{d.repo_hash}`, installed: `{d.installed_hash}`)")
        lines.append("")

    if extra:
        lines.append("### Extra Skills (installed, not in repo)")
        for d in extra:
            lines.append(f"- `{d.skill_path}`")
        lines.append("")

    if not skills_report.has_drift:
        lines.append("**Skills: IN SYNC** ✅")
    else:
        lines.append("**Skills: DRIFT DETECTED** ❌ — run `python wizard-bootstrap/skills_audit.py --fix`")
    lines.append("")
    lines.append("---")
    lines.append("")

    # 3. Dependency check
    lines.append("## 3. Cross-Wizard Dependency Check")
    lines.append("")
    dep_report = run_dep_check()

    if not dep_report.deps:
        lines.append("No explicit dependencies declared in SKILL.md frontmatter.")
        lines.append("")
        lines.append(
            "_Tip: Add a `dependencies` block to SKILL.md to make binary/env_var "
            "requirements checkable automatically._"
        )
    else:
        satisfied = sum(1 for d in dep_report.deps if d.satisfied)
        total_deps = len(dep_report.deps)
        lines.append(f"**{satisfied}/{total_deps} dependencies satisfied.**")
        lines.append("")
        if dep_report.unsatisfied:
            lines.append("### Unsatisfied Dependencies")
            for dep in dep_report.unsatisfied:
                dep_type = "binary" if dep.binary else "env_var"
                dep_name = dep.binary or dep.env_var
                lines.append(f"- `[{dep.skill_path}]` {dep_type}:`{dep_name}` — {dep.detail}")
            lines.append("")

    if dep_report.all_satisfied:
        lines.append("**Dependencies: ALL SATISFIED** ✅")
    else:
        lines.append("**Dependencies: ISSUES FOUND** ❌")
    lines.append("")
    lines.append("---")
    lines.append("")

    # Summary
    overall_ok = bootstrap.passed and not skills_report.has_drift and dep_report.all_satisfied
    lines.append("## Summary")
    lines.append("")
    lines.append(f"| Check | Status |")
    lines.append(f"|-------|--------|")
    lines.append(f"| Environment Bootstrap | {_emoji(bootstrap.passed)} |")
    lines.append(f"| Skills Drift | {_emoji(not skills_report.has_drift)} |")
    lines.append(f"| Dependency Check | {_emoji(dep_report.all_satisfied)} |")
    lines.append("")
    if overall_ok:
        lines.append("**Overall: FORGE READY** ✅")
    else:
        lines.append("**Overall: ACTION REQUIRED** ❌")
    lines.append("")

    return "\n".join(lines)


# ---------------------------------------------------------------------------
# Output / delivery
# ---------------------------------------------------------------------------

def _save_report(report: str, output_path: Path) -> None:
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(report, encoding="utf-8")
    print(f"Report saved to: {output_path}")


def _post_telegram(report: str) -> None:
    """Post the report summary to Telegram via hermes gateway if configured."""
    token = os.environ.get("TELEGRAM_BOT_TOKEN")
    channel = os.environ.get("TELEGRAM_HOME_CHANNEL") or os.environ.get("TELEGRAM_CHANNEL_ID")
    if not (token and channel):
        print("Telegram not configured (need TELEGRAM_BOT_TOKEN + TELEGRAM_HOME_CHANNEL).", file=sys.stderr)
        return

    try:
        import requests  # noqa: PLC0415

        # Extract just the summary section for Telegram (keep it brief)
        summary_start = report.find("## Summary")
        summary_text = report[summary_start:] if summary_start != -1 else report[-1000:]
        payload = {
            "chat_id": channel,
            "text": f"🧙 **Wizard Council Monthly Audit**\n\n{summary_text}",
            "parse_mode": "Markdown",
        }
        resp = requests.post(
            f"https://api.telegram.org/bot{token}/sendMessage",
            json=payload,
            timeout=15,
        )
        if resp.status_code == 200:
            print("Report summary posted to Telegram.")
        else:
            print(f"Telegram post failed: HTTP {resp.status_code}", file=sys.stderr)
    except Exception as exc:
        print(f"Telegram post error: {exc}", file=sys.stderr)


# ---------------------------------------------------------------------------
# CLI entry point
# ---------------------------------------------------------------------------

def main() -> None:
    parser = argparse.ArgumentParser(
        description="Run the monthly Wizard Council environment audit."
    )
    parser.add_argument(
        "--output",
        default=None,
        help="Path to save the Markdown report (default: ~/.hermes/wizard-council/audit-YYYY-MM.md)",
    )
    parser.add_argument(
        "--repo-root",
        default=str(_REPO_ROOT),
        help="Root of the hermes-agent repo",
    )
    parser.add_argument(
        "--post-telegram",
        action="store_true",
        help="Post the report summary to Telegram",
    )
    args = parser.parse_args()

    repo_root = Path(args.repo_root).resolve()
    report = build_report(repo_root)

    # Print to stdout
    print(report)

    # Save to default location
    now = datetime.now(timezone.utc)
    if args.output:
        output_path = Path(args.output)
    else:
        hermes_home = Path(os.environ.get("HERMES_HOME", Path.home() / ".hermes"))
        output_path = hermes_home / "wizard-council" / f"audit-{now.strftime('%Y-%m')}.md"

    _save_report(report, output_path)

    if args.post_telegram:
        _post_telegram(report)


if __name__ == "__main__":
    main()
