"""Markdown reporter for GitHub/GitLab step summaries.

Generates beautiful markdown output suitable for:
- GitHub Actions step summaries ($GITHUB_STEP_SUMMARY)
- GitLab CI job logs
- PR comments
- README badges
"""

from __future__ import annotations

from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING

from khaos.packs.contract import EvaluationReport

if TYPE_CHECKING:
    from khaos.ci.baseline import RegressionResult


class MarkdownReporter:
    """Generate Markdown report from Khaos evaluation results."""

    def __init__(
        self,
        report: EvaluationReport,
        regression_result: "RegressionResult" | None = None,
        security_threshold: int = 80,
        resilience_threshold: int = 70,
    ):
        self.report = report
        self.regression_result = regression_result
        self.security_threshold = security_threshold
        self.resilience_threshold = resilience_threshold

    def generate(self) -> str:
        """Generate Markdown report string."""
        lines = []

        # Header
        lines.append("# Khaos Evaluation Results")
        lines.append("")
        lines.append(f"**Pack:** {self.report.pack_name} v{self.report.pack_version}")
        lines.append(f"**Run ID:** `{self.report.run_id}`")
        lines.append(f"**Timestamp:** {self.report.timestamp}")
        lines.append("")

        # Overall verdict
        lines.append(self._generate_verdict())
        lines.append("")

        # Score table
        lines.append("## Scores")
        lines.append("")
        lines.append("| Metric | Score | Threshold | Status |")
        lines.append("|--------|-------|-----------|--------|")

        if self.report.security:
            passed = self.report.security.score >= self.security_threshold
            status = ":white_check_mark: Pass" if passed else ":x: Fail"
            lines.append(
                f"| Security | {self.report.security.score:.0f}/100 | {self.security_threshold} | {status} |"
            )

        if self.report.resilience:
            passed = self.report.resilience.score >= self.resilience_threshold
            status = ":white_check_mark: Pass" if passed else ":x: Fail"
            lines.append(
                f"| Resilience | {self.report.resilience.score:.0f}/100 | {self.resilience_threshold} | {status} |"
            )

        if self.report.baseline:
            lines.append(
                f"| Baseline | {self.report.baseline.task_completion_rate:.0%} completion | - | - |"
            )

        lines.append(f"| **Overall** | **{self.report.overall_score:.0f}/100** | - | - |")
        lines.append("")

        # Regression section
        if self.regression_result:
            lines.append(self._generate_regression_section())
            lines.append("")

        # Phase details
        if self.report.baseline:
            lines.append(self._generate_baseline_section())
            lines.append("")

        if self.report.resilience:
            lines.append(self._generate_resilience_section())
            lines.append("")

        if self.report.security:
            lines.append(self._generate_security_section())
            lines.append("")

        # Footer
        lines.append("---")
        lines.append(f"*Generated by Khaos SDK at {datetime.utcnow().isoformat()}Z*")

        return "\n".join(lines)

    def _generate_verdict(self) -> str:
        """Generate overall verdict banner."""
        security_passed = (
            self.report.security is None
            or self.report.security.score >= self.security_threshold
        )
        resilience_passed = (
            self.report.resilience is None
            or self.report.resilience.score >= self.resilience_threshold
        )
        regression = (
            self.regression_result and self.regression_result.has_regression
        )

        if security_passed and resilience_passed and not regression:
            return "> :white_check_mark: **All gates passed**"
        else:
            failures = []
            if not security_passed:
                failures.append("security threshold")
            if not resilience_passed:
                failures.append("resilience threshold")
            if regression:
                failures.append("regression detected")
            return f"> :x: **Failed:** {', '.join(failures)}"

    def _generate_regression_section(self) -> str:
        """Generate regression comparison section."""
        if not self.regression_result:
            return ""

        lines = ["## Baseline Comparison", ""]

        if self.regression_result.has_regression:
            lines.append(":warning: **Regression Detected**")
            lines.append("")
            lines.append(f"Comparing against baseline: `{self.regression_result.baseline_run_id}`")
            lines.append("")

            if self.regression_result.security_regressed:
                lines.append("- :x: Security score decreased")
            if self.regression_result.resilience_regressed:
                lines.append("- :x: Resilience score decreased")
            if self.regression_result.new_vulnerabilities:
                lines.append(
                    f"- :x: {len(self.regression_result.new_vulnerabilities)} new vulnerabilities found"
                )
                for vuln in self.regression_result.new_vulnerabilities[:5]:
                    lines.append(f"  - `{vuln}`")
        else:
            lines.append(":white_check_mark: **No regressions detected**")
            lines.append("")
            lines.append(f"Comparing against baseline: `{self.regression_result.baseline_run_id}`")

        return "\n".join(lines)

    def _generate_baseline_section(self) -> str:
        """Generate baseline phase section."""
        if not self.report.baseline:
            return ""

        b = self.report.baseline
        lines = [
            "## Baseline Phase",
            "",
            f"- **Runs:** {b.runs}",
            f"- **Task Completion:** {b.task_completion_rate:.0%}",
            f"- **Error Rate:** {b.error_rate:.0%}",
            f"- **Goals Met:** {b.goals_met}/{b.goals_total}",
            "",
            "### Latency",
            "",
            f"- P50: {b.latency.p50:.0f}ms",
            f"- P95: {b.latency.p95:.0f}ms",
            f"- P99: {b.latency.p99:.0f}ms",
        ]

        if b.tokens:
            lines.extend([
                "",
                "### Tokens",
                "",
                f"- Input: {b.tokens.input_total:,} total ({b.tokens.input_avg:.0f} avg)",
                f"- Output: {b.tokens.output_total:,} total ({b.tokens.output_avg:.0f} avg)",
            ])

        if b.cost_usd:
            lines.extend([
                "",
                f"### Cost: ${b.cost_usd:.4f}",
            ])

        return "\n".join(lines)

    def _generate_resilience_section(self) -> str:
        """Generate resilience phase section."""
        if not self.report.resilience:
            return ""

        r = self.report.resilience
        lines = [
            "## Resilience Phase",
            "",
            f"- **Score:** {r.score:.0f}/100",
            f"- **Runs:** {r.runs}",
            f"- **Degradation:** {r.degradation_percent:.1f}%",
            f"- **Error Rate:** {r.error_rate:.0%}",
            f"- **Recovery Rate:** {r.recovery_rate:.0%}",
        ]

        if r.fault_coverage:
            lines.extend([
                "",
                f"### Fault Coverage: {r.fault_coverage.faults_used}/{r.fault_coverage.faults_available}",
                "",
            ])
            for fault_type in r.fault_coverage.fault_types_tested[:10]:
                lines.append(f"- `{fault_type}`")

        if r.fault_impacts:
            lines.extend([
                "",
                "### Fault Impacts",
                "",
                "| Fault | Latency Impact | Error Rate | Recovered |",
                "|-------|---------------|------------|-----------|",
            ])
            for impact in r.fault_impacts[:10]:
                recovered = ":white_check_mark:" if impact.recovered else ":x:"
                lines.append(
                    f"| `{impact.fault_type}` | +{impact.latency_increase_percent:.0f}% | "
                    f"+{impact.error_rate_increase:.0%} | {recovered} |"
                )

        return "\n".join(lines)

    def _generate_security_section(self) -> str:
        """Generate security phase section."""
        if not self.report.security:
            return ""

        s = self.report.security
        attack_results = getattr(s, "attack_results", None) or []
        blocked = sum(1 for a in attack_results if getattr(a, "classification", "") == "blocked") if attack_results else None
        inconclusive = sum(1 for a in attack_results if getattr(a, "classification", "") == "inconclusive") if attack_results else None
        compromised = sum(1 for a in attack_results if getattr(a, "classification", "") == "compromised") if attack_results else None
        custom_total = sum(1 for a in attack_results if getattr(a, "is_custom", False)) if attack_results else None
        lines = [
            "## Security Phase",
            "",
            f"- **Score:** {s.score:.0f}/100",
            f"- **Attacks Tested:** {s.attacks_tested}",
            f"- **Attacks Blocked:** {s.attacks_blocked}",
            f"- **Attacks Passed:** {s.attacks_passed}",
        ]

        if attack_results and blocked is not None and inconclusive is not None and compromised is not None:
            lines.extend([
                f"- **Outcomes:** {blocked} blocked • {inconclusive} inconclusive • {compromised} compromised",
                f"- **Custom Attacks:** {custom_total}",
            ])

        # Vulnerability summary
        total_vulns = (
            s.critical_vulnerabilities
            + s.high_vulnerabilities
            + s.medium_vulnerabilities
            + s.low_vulnerabilities
        )
        if total_vulns > 0:
            lines.extend([
                "",
                "### Vulnerabilities Found",
                "",
                f"- :red_circle: Critical: {s.critical_vulnerabilities}",
                f"- :orange_circle: High: {s.high_vulnerabilities}",
                f"- :yellow_circle: Medium: {s.medium_vulnerabilities}",
                f"- :white_circle: Low: {s.low_vulnerabilities}",
            ])

        if s.vulnerable_categories:
            lines.extend([
                "",
                "### Vulnerable Categories",
                "",
            ])
            for cat in s.vulnerable_categories[:10]:
                lines.append(f"- `{cat}`")

        if attack_results:
            lines.extend([
                "",
                "### Attack Outcomes",
                "",
                "| Attack | Severity | Vector | Custom | Result |",
                "|--------|----------|--------|--------|--------|",
            ])

            def label(a: object) -> str:
                attack_id = str(getattr(a, "attack_id", "") or "")
                attack_name = str(getattr(a, "attack_name", "") or "")
                return attack_id or attack_name or "unknown"

            for attack in attack_results[:25]:
                lines.append(
                    "| "
                    + " | ".join([
                        f"`{label(attack)}`",
                        str(getattr(attack, "severity", "medium") or "medium"),
                        str(getattr(attack, "injection_vector", "user_input") or "user_input"),
                        "yes" if bool(getattr(attack, "is_custom", False)) else "no",
                        str(getattr(attack, "classification", "inconclusive") or "inconclusive"),
                    ])
                    + " |"
                )

        return "\n".join(lines)

    def write(self, path: Path) -> None:
        """Write Markdown to file."""
        path = Path(path)
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(self.generate())
