"""
AIPTX Key Validation Report Generator
=====================================

Generates comprehensive reports from key validation results.

Supports:
- JSON reports
- HTML reports
- Markdown reports
"""

from __future__ import annotations

import json
import time
from typing import Any, Optional
from pathlib import Path
from dataclasses import dataclass

from .base import ValidationResult, RiskLevel, KeyType


@dataclass
class ReportConfig:
    """Report generation configuration."""

    include_raw_keys: bool = False  # Don't include actual key values by default
    include_raw_response: bool = False
    include_attack_vectors: bool = True
    max_resources_per_key: int = 20
    group_by_risk: bool = True


class KeyValidationReportGenerator:
    """Generate reports from key validation results."""

    def __init__(self, config: Optional[ReportConfig] = None):
        """Initialize report generator."""
        self.config = config or ReportConfig()

    def generate_json_report(
        self,
        results: list[ValidationResult],
        scan_info: Optional[dict] = None,
    ) -> dict:
        """
        Generate JSON report from validation results.

        Args:
            results: List of validation results
            scan_info: Optional scan metadata

        Returns:
            Report dictionary
        """
        valid_results = [r for r in results if r.is_valid]
        invalid_results = [r for r in results if not r.is_valid]

        # Count by risk level
        by_risk = self._count_by_risk(valid_results)

        # Count by key type
        by_type = self._count_by_type(valid_results)

        # Collect attack vectors
        attack_vectors = self._collect_attack_vectors(valid_results)

        report = {
            "report_type": "key_validation",
            "generated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
            "scan_info": scan_info or {},
            "summary": {
                "total_keys_checked": len(results),
                "valid_keys": len(valid_results),
                "invalid_keys": len(invalid_results),
                "risk_breakdown": by_risk,
                "type_breakdown": by_type,
                "unique_attack_vectors": len(attack_vectors),
            },
            "attack_vectors": attack_vectors if self.config.include_attack_vectors else [],
            "findings": [],
        }

        # Add findings
        if self.config.group_by_risk:
            report["findings_by_risk"] = {
                "critical": [],
                "high": [],
                "medium": [],
                "low": [],
                "info": [],
            }
            for result in valid_results:
                finding = self._result_to_finding(result)
                report["findings_by_risk"][result.risk_level.value].append(finding)
            report["findings"] = report["findings_by_risk"]
        else:
            report["findings"] = [
                self._result_to_finding(r) for r in valid_results
            ]

        # Add invalid keys summary
        if invalid_results:
            report["invalid_keys"] = [
                {
                    "key_type": r.key_info.key_type.value,
                    "masked_key": r.key_info.masked_value,
                    "error": r.error,
                    "error_code": r.error_code,
                }
                for r in invalid_results
            ]

        return report

    def generate_html_report(
        self,
        results: list[ValidationResult],
        scan_info: Optional[dict] = None,
    ) -> str:
        """
        Generate HTML report from validation results.

        Args:
            results: List of validation results
            scan_info: Optional scan metadata

        Returns:
            HTML string
        """
        json_report = self.generate_json_report(results, scan_info)

        # Risk level colors
        risk_colors = {
            "critical": "#dc3545",
            "high": "#fd7e14",
            "medium": "#ffc107",
            "low": "#17a2b8",
            "info": "#6c757d",
        }

        html = f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AIPTX Key Validation Report</title>
    <style>
        * {{ margin: 0; padding: 0; box-sizing: border-box; }}
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            background: #0d1117;
            color: #c9d1d9;
            line-height: 1.6;
            padding: 20px;
        }}
        .container {{ max-width: 1200px; margin: 0 auto; }}
        h1 {{ color: #58a6ff; margin-bottom: 20px; }}
        h2 {{ color: #8b949e; margin: 20px 0 10px; border-bottom: 1px solid #30363d; padding-bottom: 10px; }}
        h3 {{ color: #58a6ff; margin: 15px 0 10px; }}
        .summary-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin: 20px 0;
        }}
        .summary-card {{
            background: #161b22;
            border: 1px solid #30363d;
            border-radius: 8px;
            padding: 20px;
            text-align: center;
        }}
        .summary-card .value {{
            font-size: 2.5em;
            font-weight: bold;
            color: #58a6ff;
        }}
        .summary-card .label {{ color: #8b949e; margin-top: 5px; }}
        .risk-badge {{
            display: inline-block;
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 0.85em;
            font-weight: 600;
            text-transform: uppercase;
        }}
        .risk-critical {{ background: {risk_colors['critical']}; color: white; }}
        .risk-high {{ background: {risk_colors['high']}; color: white; }}
        .risk-medium {{ background: {risk_colors['medium']}; color: black; }}
        .risk-low {{ background: {risk_colors['low']}; color: white; }}
        .risk-info {{ background: {risk_colors['info']}; color: white; }}
        .finding-card {{
            background: #161b22;
            border: 1px solid #30363d;
            border-radius: 8px;
            padding: 20px;
            margin: 15px 0;
        }}
        .finding-header {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }}
        .finding-type {{ font-size: 1.2em; font-weight: 600; color: #58a6ff; }}
        .finding-detail {{ margin: 10px 0; }}
        .finding-detail .label {{ color: #8b949e; font-weight: 500; }}
        .finding-detail .value {{ color: #c9d1d9; }}
        .permissions-list, .resources-list {{
            list-style: none;
            margin: 5px 0;
            padding-left: 20px;
        }}
        .permissions-list li, .resources-list li {{
            padding: 3px 0;
            color: #8b949e;
        }}
        .permissions-list li::before {{ content: "✓ "; color: #3fb950; }}
        .resources-list li::before {{ content: "→ "; color: #58a6ff; }}
        .attack-vectors {{
            background: #1f1f1f;
            border-left: 3px solid #dc3545;
            padding: 15px;
            margin: 10px 0;
        }}
        .attack-vectors h4 {{ color: #dc3545; margin-bottom: 10px; }}
        .attack-vectors ul {{ list-style: none; }}
        .attack-vectors li {{
            padding: 5px 0;
            color: #f85149;
        }}
        .attack-vectors li::before {{ content: "⚠ "; }}
        .footer {{
            margin-top: 40px;
            padding-top: 20px;
            border-top: 1px solid #30363d;
            text-align: center;
            color: #8b949e;
        }}
        code {{
            background: #1f1f1f;
            padding: 2px 6px;
            border-radius: 4px;
            font-family: 'Monaco', 'Menlo', monospace;
            font-size: 0.9em;
        }}
    </style>
</head>
<body>
    <div class="container">
        <h1>🔑 AIPTX Key Validation Report</h1>
        <p style="color: #8b949e;">Generated: {json_report['generated_at']}</p>

        <h2>Summary</h2>
        <div class="summary-grid">
            <div class="summary-card">
                <div class="value">{json_report['summary']['total_keys_checked']}</div>
                <div class="label">Total Keys Checked</div>
            </div>
            <div class="summary-card">
                <div class="value" style="color: #3fb950;">{json_report['summary']['valid_keys']}</div>
                <div class="label">Valid Keys</div>
            </div>
            <div class="summary-card">
                <div class="value" style="color: #dc3545;">{json_report['summary']['risk_breakdown'].get('critical', 0)}</div>
                <div class="label">Critical Risk</div>
            </div>
            <div class="summary-card">
                <div class="value" style="color: #fd7e14;">{json_report['summary']['risk_breakdown'].get('high', 0)}</div>
                <div class="label">High Risk</div>
            </div>
        </div>

        <h2>Risk Breakdown</h2>
        <div class="summary-grid">
"""

        for risk, count in json_report['summary']['risk_breakdown'].items():
            html += f"""
            <div class="summary-card">
                <span class="risk-badge risk-{risk}">{risk}</span>
                <div class="value">{count}</div>
            </div>
"""

        html += """
        </div>
"""

        # Add attack vectors section
        if json_report.get('attack_vectors'):
            html += """
        <h2>Attack Vectors Identified</h2>
        <div class="attack-vectors">
            <ul>
"""
            for vector in json_report['attack_vectors'][:15]:
                html += f"                <li>{vector}</li>\n"
            html += """
            </ul>
        </div>
"""

        # Add findings
        html += """
        <h2>Validated Keys</h2>
"""

        if self.config.group_by_risk:
            for risk_level in ['critical', 'high', 'medium', 'low', 'info']:
                findings = json_report.get('findings_by_risk', {}).get(risk_level, [])
                if findings:
                    html += f"""
        <h3><span class="risk-badge risk-{risk_level}">{risk_level.upper()}</span> ({len(findings)} keys)</h3>
"""
                    for finding in findings:
                        html += self._finding_to_html(finding)

        html += f"""
        <div class="footer">
            <p>Generated by AIPTX - AI-Powered Penetration Testing</p>
            <p>Total findings: {json_report['summary']['valid_keys']} valid keys detected</p>
        </div>
    </div>
</body>
</html>
"""

        return html

    def generate_markdown_report(
        self,
        results: list[ValidationResult],
        scan_info: Optional[dict] = None,
    ) -> str:
        """
        Generate Markdown report from validation results.

        Args:
            results: List of validation results
            scan_info: Optional scan metadata

        Returns:
            Markdown string
        """
        json_report = self.generate_json_report(results, scan_info)

        md = f"""# 🔑 AIPTX Key Validation Report

**Generated:** {json_report['generated_at']}

## Summary

| Metric | Value |
|--------|-------|
| Total Keys Checked | {json_report['summary']['total_keys_checked']} |
| Valid Keys | {json_report['summary']['valid_keys']} |
| Invalid Keys | {json_report['summary']['invalid_keys']} |

### Risk Breakdown

| Risk Level | Count |
|------------|-------|
"""

        for risk, count in json_report['summary']['risk_breakdown'].items():
            emoji = {"critical": "🔴", "high": "🟠", "medium": "🟡", "low": "🔵", "info": "⚪"}.get(risk, "")
            md += f"| {emoji} {risk.upper()} | {count} |\n"

        md += "\n### Key Types\n\n"
        for key_type, count in json_report['summary']['type_breakdown'].items():
            md += f"- **{key_type.upper()}**: {count}\n"

        if json_report.get('attack_vectors'):
            md += "\n## ⚠️ Attack Vectors\n\n"
            for vector in json_report['attack_vectors']:
                md += f"- {vector}\n"

        md += "\n## Findings\n\n"

        if self.config.group_by_risk:
            for risk_level in ['critical', 'high', 'medium', 'low', 'info']:
                findings = json_report.get('findings_by_risk', {}).get(risk_level, [])
                if findings:
                    emoji = {"critical": "🔴", "high": "🟠", "medium": "🟡", "low": "🔵", "info": "⚪"}.get(risk_level, "")
                    md += f"\n### {emoji} {risk_level.upper()} ({len(findings)})\n\n"

                    for finding in findings:
                        md += self._finding_to_markdown(finding)

        md += "\n---\n\n*Generated by AIPTX - AI-Powered Penetration Testing*\n"

        return md

    def _result_to_finding(self, result: ValidationResult) -> dict:
        """Convert ValidationResult to finding dictionary."""
        finding = {
            "key_type": result.key_info.key_type.value,
            "risk_level": result.risk_level.value,
            "masked_key": result.key_info.masked_value,
            "identity": result.identity_info,
            "permissions": result.permissions,
            "resources": result.resources_accessible[:self.config.max_resources_per_key],
            "exploitation_potential": result.exploitation_potential,
            "validation_method": result.validation_method,
            "validated_at": result.validated_at,
        }

        if self.config.include_attack_vectors and result.attack_vectors:
            finding["attack_vectors"] = result.attack_vectors

        if self.config.include_raw_keys:
            finding["key_value"] = result.key_info.key_value

        if self.config.include_raw_response:
            finding["raw_response"] = result.raw_response

        return finding

    def _finding_to_html(self, finding: dict) -> str:
        """Convert finding to HTML card."""
        identity_html = ""
        for key, value in finding.get('identity', {}).items():
            if value:
                identity_html += f'<div class="finding-detail"><span class="label">{key}:</span> <span class="value">{value}</span></div>\n'

        permissions_html = ""
        if finding.get('permissions'):
            permissions_html = '<ul class="permissions-list">'
            for perm in finding['permissions'][:10]:
                permissions_html += f"<li>{perm}</li>"
            permissions_html += "</ul>"

        resources_html = ""
        if finding.get('resources'):
            resources_html = '<ul class="resources-list">'
            for res in finding['resources'][:10]:
                resources_html += f"<li>{res}</li>"
            resources_html += "</ul>"

        attack_vectors_html = ""
        if finding.get('attack_vectors'):
            attack_vectors_html = '<div class="attack-vectors"><h4>Attack Vectors</h4><ul>'
            for vector in finding['attack_vectors']:
                attack_vectors_html += f"<li>{vector}</li>"
            attack_vectors_html += "</ul></div>"

        return f"""
        <div class="finding-card">
            <div class="finding-header">
                <span class="finding-type">{finding['key_type'].upper()}</span>
                <span class="risk-badge risk-{finding['risk_level']}">{finding['risk_level'].upper()}</span>
            </div>
            <div class="finding-detail">
                <span class="label">Key:</span>
                <code>{finding['masked_key']}</code>
            </div>
            {identity_html}
            <div class="finding-detail">
                <span class="label">Exploitation Potential:</span>
                <span class="value">{finding.get('exploitation_potential', 'N/A')}</span>
            </div>
            <h4 style="margin-top: 15px; color: #8b949e;">Permissions</h4>
            {permissions_html}
            <h4 style="margin-top: 15px; color: #8b949e;">Resources</h4>
            {resources_html}
            {attack_vectors_html}
        </div>
"""

    def _finding_to_markdown(self, finding: dict) -> str:
        """Convert finding to Markdown."""
        md = f"""#### {finding['key_type'].upper()} - `{finding['masked_key']}`

**Exploitation Potential:** {finding.get('exploitation_potential', 'N/A')}

**Identity:**
"""
        for key, value in finding.get('identity', {}).items():
            if value:
                md += f"- {key}: `{value}`\n"

        if finding.get('permissions'):
            md += "\n**Permissions:**\n"
            for perm in finding['permissions'][:10]:
                md += f"- ✓ {perm}\n"

        if finding.get('resources'):
            md += "\n**Resources:**\n"
            for res in finding['resources'][:10]:
                md += f"- → {res}\n"

        if finding.get('attack_vectors'):
            md += "\n**Attack Vectors:**\n"
            for vector in finding['attack_vectors']:
                md += f"- ⚠️ {vector}\n"

        md += "\n---\n\n"
        return md

    def _count_by_risk(self, results: list[ValidationResult]) -> dict[str, int]:
        """Count results by risk level."""
        counts = {
            "critical": 0,
            "high": 0,
            "medium": 0,
            "low": 0,
            "info": 0,
        }
        for result in results:
            counts[result.risk_level.value] = counts.get(result.risk_level.value, 0) + 1
        return counts

    def _count_by_type(self, results: list[ValidationResult]) -> dict[str, int]:
        """Count results by key type."""
        counts = {}
        for result in results:
            key_type = result.key_info.key_type.value
            counts[key_type] = counts.get(key_type, 0) + 1
        return counts

    def _collect_attack_vectors(
        self,
        results: list[ValidationResult],
    ) -> list[str]:
        """Collect unique attack vectors."""
        vectors = set()
        for result in results:
            if result.attack_vectors:
                vectors.update(result.attack_vectors)
        return sorted(vectors)

    def save_report(
        self,
        results: list[ValidationResult],
        output_path: str,
        format: str = "json",
        scan_info: Optional[dict] = None,
    ) -> str:
        """
        Save report to file.

        Args:
            results: Validation results
            output_path: Output file path
            format: Report format (json, html, md)
            scan_info: Optional scan metadata

        Returns:
            Path to saved report
        """
        path = Path(output_path)

        if format == "json":
            report = self.generate_json_report(results, scan_info)
            path.write_text(json.dumps(report, indent=2))
        elif format == "html":
            report = self.generate_html_report(results, scan_info)
            path.write_text(report)
        elif format in ("md", "markdown"):
            report = self.generate_markdown_report(results, scan_info)
            path.write_text(report)
        else:
            raise ValueError(f"Unsupported format: {format}")

        return str(path)
