"""
Report Generator: Scientific Integrity Reports

Generates comprehensive reports on code scientific integrity
in multiple formats (Markdown, HTML, JSON).
"""

import json
from dataclasses import dataclass
from datetime import datetime
from typing import Any, Dict, List, Optional, cast


@dataclass
class ReportSection:
    """A section in the integrity report."""

    title: str
    status: str  # 'pass', 'warning', 'fail'
    content: str
    issues: List[Dict[str, Any]]
    recommendations: List[str]


class IntegrityReportGenerator:
    """
    Generates scientific integrity reports in multiple formats.

    Usage:
        generator = IntegrityReportGenerator()
        generator.add_section("Mirages", "pass", "No mirages detected", [], [])
        markdown = generator.to_markdown()
        html = generator.to_html()
    """

    def __init__(self, title: str = "Demyst Check Report"):
        """
        Initialize report generator.

        Args:
            title: Report title
        """
        self.title = title
        self.sections: List[ReportSection] = []
        self.metadata: Dict[str, Any] = {
            "timestamp": datetime.now().isoformat(),
            "version": "1.0.0",
        }

    def add_section(
        self,
        title: str,
        status: str,
        content: str,
        issues: List[Dict[str, Any]],
        recommendations: List[str],
    ) -> None:
        """Add a section to the report."""
        self.sections.append(
            ReportSection(
                title=title,
                status=status,
                content=content,
                issues=issues,
                recommendations=recommendations,
            )
        )

    def add_metadata(self, key: str, value: Any) -> None:
        """Add metadata to the report."""
        self.metadata[key] = value

    def get_overall_status(self) -> str:
        """Determine overall report status."""
        statuses = [s.status for s in self.sections]
        if "fail" in statuses:
            return "fail"
        elif "warning" in statuses:
            return "warning"
        else:
            return "pass"

    def to_markdown(self) -> str:
        """Generate Markdown report."""
        lines = [
            f"# {self.title}",
            "",
            f"**Generated:** {self.metadata.get('timestamp', 'Unknown')}",
            f"**Status:** {self._status_badge(self.get_overall_status())}",
            "",
            "---",
            "",
        ]

        # Summary table
        lines.extend(
            [
                "## Summary",
                "",
                "| Check | Status |",
                "|-------|--------|",
            ]
        )

        for section in self.sections:
            status_icon = self._status_icon(section.status)
            lines.append(f"| {section.title} | {status_icon} |")

        lines.extend(["", "---", ""])

        # Detailed sections
        for section in self.sections:
            lines.extend(self._section_to_markdown(section))

        # Footer
        lines.extend(
            [
                "---",
                "",
                "*Generated by Demyst Scientific Integrity Platform*",
            ]
        )

        return "\n".join(lines)

    def _section_to_markdown(self, section: ReportSection) -> List[str]:
        """Convert a section to Markdown lines."""
        lines = [
            f"## {self._status_icon(section.status)} {section.title}",
            "",
            section.content,
            "",
        ]

        if section.issues:
            lines.extend(
                [
                    "### Issues Found",
                    "",
                ]
            )
            for issue in section.issues[:20]:  # Limit to 20
                line = issue.get("line", "?")
                desc = issue.get("description", str(issue))
                severity = issue.get("severity", "info")
                confidence = issue.get("confidence", "unknown")
                blocking = issue.get("blocking", False)
                lines.append(
                    f"- **Line {line}** ({severity}, confidence={confidence}, blocking={blocking}): {desc}"
                )
            if len(section.issues) > 20:
                lines.append(f"- *...and {len(section.issues) - 20} more issues*")
            lines.append("")

        if section.recommendations:
            lines.extend(
                [
                    "### Recommendations",
                    "",
                ]
            )
            for rec in section.recommendations:
                lines.append(f"- {rec}")
            lines.append("")

        return lines

    def _status_icon(self, status: str) -> str:
        """Get status icon for Markdown."""
        return {
            "pass": ":white_check_mark:",
            "warning": ":warning:",
            "fail": ":x:",
        }.get(status, ":question:")

    def _status_badge(self, status: str) -> str:
        """Get status badge for Markdown."""
        color = {"pass": "brightgreen", "warning": "yellow", "fail": "red"}.get(status, "gray")
        return f"![Status](https://img.shields.io/badge/integrity-{status}-{color})"

    def to_html(self) -> str:
        """Generate HTML report."""
        status = self.get_overall_status()
        status_color = {"pass": "#28a745", "warning": "#ffc107", "fail": "#dc3545"}.get(
            status, "#6c757d"
        )

        sections_html = ""
        for section in self.sections:
            sections_html += self._section_to_html(section)

        return f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{self.title}</title>
    <style>
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
        }}
        h1 {{ border-bottom: 2px solid {status_color}; padding-bottom: 10px; }}
        .status-badge {{
            display: inline-block;
            padding: 5px 15px;
            border-radius: 20px;
            color: white;
            background-color: {status_color};
            font-weight: bold;
        }}
        .section {{
            margin: 20px 0;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 8px;
        }}
        .section.pass {{ border-left: 4px solid #28a745; }}
        .section.warning {{ border-left: 4px solid #ffc107; }}
        .section.fail {{ border-left: 4px solid #dc3545; }}
        .issue {{
            background: #f8f9fa;
            padding: 10px;
            margin: 5px 0;
            border-radius: 4px;
            font-family: monospace;
            font-size: 0.9em;
        }}
        .issue.critical {{ border-left: 3px solid #dc3545; }}
        .issue.warning {{ border-left: 3px solid #ffc107; }}
        .recommendation {{
            background: #e7f5ff;
            padding: 10px;
            margin: 5px 0;
            border-radius: 4px;
            border-left: 3px solid #0066cc;
        }}
        table {{ width: 100%; border-collapse: collapse; margin: 15px 0; }}
        th, td {{ padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }}
        th {{ background-color: #f8f9fa; }}
        footer {{ margin-top: 30px; text-align: center; color: #6c757d; font-size: 0.9em; }}
    </style>
</head>
<body>
    <h1>{self.title}</h1>
    <p>
        <span class="status-badge">{status.upper()}</span>
        <span style="margin-left: 10px; color: #6c757d;">Generated: {self.metadata.get('timestamp', 'Unknown')}</span>
    </p>

    <h2>Summary</h2>
    <table>
        <tr>
            <th>Check</th>
            <th>Status</th>
            <th>Issues</th>
        </tr>
        {''.join(f'<tr><td>{s.title}</td><td>{self._status_html(s.status)}</td><td>{len(s.issues)}</td></tr>' for s in self.sections)}
    </table>

    {sections_html}

    <footer>
        <p>Generated by <strong>Demyst</strong> - The Scientific Integrity Platform</p>
    </footer>
</body>
</html>"""

    def _section_to_html(self, section: ReportSection) -> str:
        """Convert a section to HTML."""
        issues_html = ""
        if section.issues:
            issues_html = "<h4>Issues</h4>"
            for issue in section.issues[:20]:
                severity = issue.get("severity", "info")
                desc = issue.get("description", str(issue))
                line = issue.get("line", "?")
                confidence = issue.get("confidence", "unknown")
                blocking = issue.get("blocking", False)
                issues_html += (
                    f'<div class="issue {severity}"><strong>Line {line}</strong> '
                    f"({severity}, confidence={confidence}, blocking={blocking}): {desc}</div>"
                )

        recs_html = ""
        if section.recommendations:
            recs_html = "<h4>Recommendations</h4>"
            for rec in section.recommendations:
                recs_html += f'<div class="recommendation">{rec}</div>'

        return f"""
    <div class="section {section.status}">
        <h3>{self._status_html(section.status)} {section.title}</h3>
        <p>{section.content}</p>
        {issues_html}
        {recs_html}
    </div>
"""

    def _status_html(self, status: str) -> str:
        """Get status HTML element."""
        icons = {"pass": "&#x2714;", "warning": "&#x26A0;", "fail": "&#x2718;"}
        colors = {"pass": "#28a745", "warning": "#ffc107", "fail": "#dc3545"}
        return (
            f'<span style="color: {colors.get(status, "#6c757d")}">{icons.get(status, "?")}</span>'
        )

    def to_json(self) -> str:
        """Generate JSON report."""
        return json.dumps(
            {
                "title": self.title,
                "metadata": self.metadata,
                "overall_status": self.get_overall_status(),
                "sections": [
                    {
                        "title": s.title,
                        "status": s.status,
                        "content": s.content,
                        "issues": s.issues,
                        "recommendations": s.recommendations,
                    }
                    for s in self.sections
                ],
            },
            indent=2,
        )

    def to_dict(self) -> Dict[str, Any]:
        """Convert report to dictionary."""
        return cast(Dict[str, Any], json.loads(self.to_json()))

    def generate_certificate(self, code_map: Dict[str, str]) -> Dict[str, Any]:
        """
        Generate a Certificate of Integrity.

        Args:
            code_map: Dictionary mapping filenames to their content (for hashing).

        Returns:
            Dictionary containing the certificate data.

        Raises:
            ValueError: If DEMYST_SECRET_KEY environment variable is not configured.
        """
        import hashlib

        from demyst.security import sign_code

        # Calculate file hashes with proper hash chaining (prevents collision attacks)
        file_hashes = {}
        combined_hash = hashlib.sha256()
        for filename, content in sorted(code_map.items()):
            file_hash = hashlib.sha256(content.encode()).hexdigest()
            file_hashes[filename] = file_hash
            # Include filename in hash to prevent ordering attacks
            combined_hash.update(f"{filename}:{file_hash}".encode())

        combined_hash_input = combined_hash.hexdigest()

        # Sign the combined hash and verdict
        verdict = self.get_overall_status().upper()
        signature_data = sign_code(combined_hash_input, verdict)

        return {
            "certificate_version": "1.0",
            "certificate_id": signature_data["signature"][:16],
            "verdict": verdict,
            "timestamp": signature_data["timestamp"],
            "demyst_version": self.metadata.get("version", "unknown"),
            "files": file_hashes,
            "signature": signature_data["signature"],
            "verification_method": "HMAC-SHA256",
            "issuer": "Demystified Integrity Platform",
        }
