"""Persona-specific Rich formatting for certificate triage reports."""

from collections import Counter
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Dict, List, Optional

from rich.console import Console
from rich.panel import Panel
from rich.table import Table

from runbooks.common.rich_utils import console as default_console
from runbooks.inventory.models.certificate import (
    CertificateInventoryResult,
    CertificateInventorySummary,
    CertificateRecord,
    ExpiryBucket,
)


@dataclass
class CertPersonaConfig:
    """Configuration for a persona rendering mode."""

    persona: str
    title: str


def _risk_border_style(summary: CertificateInventorySummary) -> str:
    buckets = summary.by_expiry_bucket
    if buckets.get("EXPIRED", 0) > 0 or buckets.get("CRITICAL_7D", 0) > 0:
        return "bold red"
    return "yellow" if buckets.get("WARNING_30D", 0) > 0 else "green"


def _risk_label(summary: CertificateInventorySummary) -> str:
    buckets = summary.by_expiry_bucket
    if buckets.get("EXPIRED", 0) > 0 or buckets.get("CRITICAL_7D", 0) > 0:
        return "CRITICAL"
    return "WARNING" if buckets.get("WARNING_30D", 0) > 0 else "HEALTHY"


_BUCKET_STYLE = {
    ExpiryBucket.EXPIRED: "bold red",
    ExpiryBucket.CRITICAL_7D: "red",
    ExpiryBucket.WARNING_30D: "yellow",
    ExpiryBucket.ATTENTION_90D: "cyan",
    ExpiryBucket.VALID: "green",
}


def _bucket_style(bucket: ExpiryBucket) -> str:
    return _BUCKET_STYLE.get(bucket, "white")


def _sort_key(cert: CertificateRecord) -> int:
    return cert.days_until_expiry if cert.days_until_expiry is not None else -9999


class CertPersonaFormatter:
    """Persona-aware Rich renderer for certificate triage output."""

    CONFIGS = {
        "executive": CertPersonaConfig("executive", "Executive Certificate Review"),
        "cto": CertPersonaConfig("cto", "CTO Certificate Risk by Account"),
        "sre": CertPersonaConfig("sre", "SRE Alert -- Actionable Certificates"),
        "cloudops": CertPersonaConfig("cloudops", "CloudOps Certificate Triage"),
    }

    def __init__(self, persona: str = "cloudops") -> None:
        self.persona = persona
        self.config = self.CONFIGS.get(persona, self.CONFIGS["cloudops"])

    def format_executive_summary(
        self, result: CertificateInventoryResult, console: Optional[Console] = None
    ) -> Dict[str, Any]:
        """Board-ready risk summary with panels."""
        c = console or default_console
        summary = result.build_summary()
        style, risk = _risk_border_style(summary), _risk_label(summary)
        expired_in_use = sum(
            1 for cert in result.certificates if cert.expiry_bucket == ExpiryBucket.EXPIRED and cert.in_use
        )
        at_risk = summary.by_expiry_bucket.get("EXPIRED", 0) + summary.by_expiry_bucket.get("CRITICAL_7D", 0)
        accounts = len(set(cert.account_id for cert in result.certificates))
        c.print(
            Panel(
                f"[{style}]Risk Level: {risk}[/{style}]\n"
                f"{summary.total_certificates} certificates across {accounts} accounts\n"
                f"At-risk: {at_risk} | Expired + in-use: {expired_in_use}",
                title="Certificate Risk Assessment",
                border_style=style,
            )
        )
        buckets = summary.by_expiry_bucket
        lines = [
            f"  {lbl}: {buckets.get(k, 0)}"
            for k, lbl in [
                ("EXPIRED", "Expired"),
                ("CRITICAL_7D", "Critical (<=7d)"),
                ("WARNING_30D", "Warning (<=30d)"),
                ("ATTENTION_90D", "Attention (<=90d)"),
                ("VALID", "Valid"),
            ]
        ]
        c.print(Panel("\n".join(lines), title="Triage Summary", border_style="dim"))
        acct_risk: Counter = Counter()
        for cert in result.certificates:
            if cert.expiry_bucket in (ExpiryBucket.EXPIRED, ExpiryBucket.CRITICAL_7D, ExpiryBucket.WARNING_30D):
                acct_risk[cert.account_name or cert.account_id or "unknown"] += 1
        if acct_risk:
            tbl = Table(title="Top Accounts by Risk", show_header=True, header_style="bold cyan")
            tbl.add_column("Account")
            tbl.add_column("At-Risk Certs", justify="right")
            for acct, cnt in acct_risk.most_common(5):
                tbl.add_row(acct, str(cnt))
            c.print(tbl)
        actions = []
        if expired_in_use > 0:
            actions.append(f"[bold red]RENEW {expired_in_use} expired in-use certs immediately[/bold red]")
        expired_unused = summary.by_expiry_bucket.get("EXPIRED", 0) - expired_in_use
        if expired_unused > 0:
            actions.append(f"[yellow]DELETE {expired_unused} expired unused certificates[/yellow]")
        if summary.by_expiry_bucket.get("WARNING_30D", 0) > 0:
            actions.append(
                f"[dim yellow]SCHEDULE renewal for {summary.by_expiry_bucket['WARNING_30D']} certs expiring within 30 days[/dim yellow]"
            )
        if actions:
            c.print(Panel("\n".join(actions), title="Recommended Actions", border_style="cyan"))
        return {
            "persona": "executive",
            "risk_level": risk,
            "total_certs": summary.total_certificates,
            "at_risk_count": at_risk,
        }

    def format_cto_report(
        self, result: CertificateInventoryResult, console: Optional[Console] = None
    ) -> Dict[str, Any]:
        """Account-level risk breakdown for CTO."""
        c = console or default_console
        summary = result.build_summary()
        c.print(
            Panel(f"[bold]{self.config.title}[/bold]\n{summary.total_certificates} certificates", border_style="blue")
        )
        accounts: Dict[str, List[CertificateRecord]] = {}
        for cert in result.certificates:
            accounts.setdefault(cert.account_name or cert.account_id or "unknown", []).append(cert)
        tbl = Table(show_header=True, header_style="bold cyan", show_lines=True)
        for col, kw in [
            ("Account", {}),
            ("Total", {"justify": "right"}),
            ("Expired", {"justify": "right"}),
            ("In-Use", {"justify": "right"}),
            ("Auto-Renew", {"justify": "right"}),
            ("Risk", {}),
        ]:
            tbl.add_column(col, **kw)
        per_account_risk: Dict[str, str] = {}
        for acct, certs in sorted(accounts.items()):
            expired = sum(1 for cert in certs if cert.expiry_bucket == ExpiryBucket.EXPIRED)
            risk = "CRITICAL" if expired > 0 else "OK"
            rs = "bold red" if risk == "CRITICAL" else "green"
            tbl.add_row(
                acct,
                str(len(certs)),
                str(expired),
                str(sum(1 for cert in certs if cert.in_use)),
                str(sum(1 for cert in certs if cert.auto_renewal_eligible)),
                f"[{rs}]{risk}[/{rs}]",
            )
            per_account_risk[acct] = risk
        c.print(tbl)
        return {"persona": "cto", "accounts": len(accounts), "per_account_risk": per_account_risk}

    def format_sre_alerts(
        self, result: CertificateInventoryResult, console: Optional[Console] = None
    ) -> Dict[str, Any]:
        """EXPIRED + CRITICAL_7D certs only -- actionable alerts for SRE."""
        c = console or default_console
        at_risk = [
            cert
            for cert in result.certificates
            if cert.expiry_bucket in (ExpiryBucket.EXPIRED, ExpiryBucket.CRITICAL_7D)
        ]
        if not at_risk:
            c.print(Panel("[green]No actionable certificate alerts[/green]", title="SRE Alerts", border_style="green"))
            return {"persona": "sre", "alert_count": 0, "alerts": []}
        c.print(
            Panel(
                f"[bold red]{len(at_risk)} certificates require immediate action[/bold red]",
                title="SRE Alerts",
                border_style="red",
            )
        )
        tbl = Table(show_header=True, header_style="bold red")
        tbl.add_column("Domain", style="cyan", no_wrap=True, max_width=50)
        tbl.add_column("ARN", no_wrap=True, max_width=40)
        tbl.add_column("Days", justify="right")
        tbl.add_column("In-Use")
        tbl.add_column("Account")
        for cert in sorted(at_risk, key=_sort_key):
            days = cert.days_until_expiry
            style = _bucket_style(cert.expiry_bucket)
            arn = cert.certificate_arn
            tbl.add_row(
                cert.domain_name[:50],
                arn[-40:] if len(arn) > 40 else arn,
                f"[{style}]{days if days is not None else 'N/A'}[/{style}]",
                "[green]Yes[/green]" if cert.in_use else "[dim]No[/dim]",
                cert.account_name or cert.account_id or "unknown",
            )
        c.print(tbl)
        return {"persona": "sre", "alert_count": len(at_risk), "alerts": [cert.domain_name for cert in at_risk]}

    def format_cloudops_triage(
        self, result: CertificateInventoryResult, console: Optional[Console] = None
    ) -> Dict[str, Any]:
        """Color-coded triage table -- default CloudOps view."""
        c = console or default_console
        summary = result.build_summary()
        c.print(
            Panel(
                f"[bold]{self.config.title}[/bold]\n"
                f"{summary.total_certificates} certificates | In-use: {summary.in_use_count} | Auto-renew: {summary.auto_renewal_eligible_count}",
                border_style="blue",
            )
        )
        tbl = Table(show_header=True, header_style="bold cyan")
        tbl.add_column("Domain", style="cyan", no_wrap=True, max_width=50)
        tbl.add_column("Days", justify="right")
        tbl.add_column("Status")
        tbl.add_column("In-Use")
        tbl.add_column("Account")
        bucket_counts: Counter = Counter()
        for cert in sorted(result.certificates, key=_sort_key):
            days = cert.days_until_expiry
            style = _bucket_style(cert.expiry_bucket)
            bucket_counts[cert.expiry_bucket.value] += 1
            tbl.add_row(
                cert.domain_name[:50],
                f"[{style}]{days if days is not None else 'N/A'}[/{style}]",
                f"[{style}]{cert.expiry_bucket.value}[/{style}]",
                "[green]Yes[/green]" if cert.in_use else "[dim]No[/dim]",
                cert.account_name or cert.account_id or "unknown",
            )
        c.print(tbl)
        return {"persona": "cloudops", "bucket_counts": dict(bucket_counts)}

    @staticmethod
    def generate_stakeholder_email(result: CertificateInventoryResult, profile: str = "default") -> str:
        """Generate CFO-ready stakeholder email for cert review meeting."""
        summary = result.build_summary()
        risk = _risk_label(summary)
        total = summary.total_certificates
        accounts = len(set(cert.account_id for cert in result.certificates))
        expired_in_use = sum(
            1 for cert in result.certificates if cert.expiry_bucket == ExpiryBucket.EXPIRED and cert.in_use
        )
        expired = summary.by_expiry_bucket.get("EXPIRED", 0)
        critical = summary.by_expiry_bucket.get("CRITICAL_7D", 0)
        warning = summary.by_expiry_bucket.get("WARNING_30D", 0)
        acct_risk: Counter = Counter()
        for cert in result.certificates:
            if cert.expiry_bucket in (ExpiryBucket.EXPIRED, ExpiryBucket.CRITICAL_7D):
                acct_risk[cert.account_name or cert.account_id or "unknown"] += 1
        top = (
            "\n".join(f"  {i}. {a}: {n} certificates" for i, (a, n) in enumerate(acct_risk.most_common(3), 1))
            or "  None"
        )
        # Expiring within 30 days + in-use = action required
        expiring_soon = [
            cert
            for cert in result.certificates
            if cert.expiry_bucket in (ExpiryBucket.CRITICAL_7D, ExpiryBucket.WARNING_30D) and cert.in_use
        ]
        expiring_list = (
            "\n".join(
                f"  - {cert.domain_name} ({cert.days_until_expiry}d, {cert.account_name or cert.account_id})"
                for cert in sorted(expiring_soon, key=lambda c: c.days_until_expiry)[:10]
            )
            or "  None"
        )

        # Expired + not-in-use = safe to remove
        safe_to_remove = [
            cert for cert in result.certificates if cert.expiry_bucket == ExpiryBucket.EXPIRED and not cert.in_use
        ]
        safe_list = (
            "\n".join(
                f"  - {cert.domain_name} ({cert.account_name or cert.account_id}, expired {abs(cert.days_until_expiry)}d ago)"
                for cert in sorted(safe_to_remove, key=lambda c: c.days_until_expiry)[:15]
            )
            or "  None"
        )

        return (
            f"Subject: Weekly Certificate Status -- {risk}: {total} certs ({datetime.now().strftime('%d %b %Y')})\n\n"
            f"Dear Leadership Team,\n\nWeekly certificate status report for your review.\n\n"
            f"Risk Level: {risk}\n\nKey Metrics:\n"
            f"  - Total Certificates: {total}\n"
            f"  - Accounts Scanned: {accounts}\n"
            f"  - Expired + In-Use (CRITICAL): {expired_in_use}\n"
            f"  - Expired Total: {expired}\n"
            f"  - Expiring <=7 days: {critical}\n"
            f"  - Expiring <=30 days: {warning}\n\n"
            f"Top At-Risk Accounts:\n{top}\n\n"
            f"Recommended Actions:\n"
            f"  1. Renew {expired_in_use} expired in-use certificates immediately\n"
            f"  2. Remove {expired - expired_in_use} expired unused certificates\n"
            f"  3. Schedule renewal for {warning} certificates expiring within 30 days\n\n"
            f"\nCertificates Expiring Soon (action required):\n{expiring_list}\n\n"
            f"Expired Certificates -- Safe to Remove:\n{safe_list}\n\n"
            f"Report generated via: runbooks cert triage --mode executive (profile: {profile})\n"
            f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M')}\n"
        )
