"""Review reporter for generating formatted output.

This module provides various output formats for code review results.
"""

from __future__ import annotations

from pathlib import Path
from typing import Optional

from ieum.review.analyzer import ReviewIssue, Severity, IssueCategory
from ieum.review.reviewer import ReviewResult


class ReviewReporter:
    """Generates formatted reports from review results."""

    SEVERITY_EMOJI = {
        Severity.CRITICAL: "[CRITICAL]",
        Severity.HIGH: "[HIGH]",
        Severity.MEDIUM: "[MEDIUM]",
        Severity.LOW: "[LOW]",
        Severity.INFO: "[INFO]",
    }

    SEVERITY_COLOR = {
        Severity.CRITICAL: "red",
        Severity.HIGH: "orange",
        Severity.MEDIUM: "yellow",
        Severity.LOW: "blue",
        Severity.INFO: "gray",
    }

    def __init__(self):
        """Initialize the reporter."""
        pass

    def generate_markdown(self, result: ReviewResult) -> str:
        """Generate Markdown report.

        Args:
            result: Review result.

        Returns:
            Markdown formatted report.
        """
        lines = []

        # Header
        lines.append("# Code Review Report\n")

        # Summary
        status = "PASSED" if result.passed else "NEEDS ATTENTION"
        lines.append(f"**Status:** {status}")
        lines.append(f"**Score:** {result.score}/100")
        lines.append(f"**Files Reviewed:** {len(result.files_reviewed)}")
        lines.append(f"**Total Issues:** {len(result.issues)}\n")

        # Issue counts by severity
        if result.issues:
            lines.append("## Summary\n")
            lines.append("| Severity | Count |")
            lines.append("|----------|-------|")
            lines.append(f"| Critical | {result.critical_count} |")
            lines.append(f"| High | {result.high_count} |")
            lines.append(f"| Medium | {result.medium_count} |")
            lines.append(f"| Low | {result.low_count} |")
            lines.append(f"| Info | {result.info_count} |")
            lines.append("")

        # Group issues by file
        issues_by_file = self._group_by_file(result.issues)

        if issues_by_file:
            lines.append("## Issues by File\n")

            for file_path, issues in issues_by_file.items():
                lines.append(f"### {file_path}\n")

                for issue in sorted(issues, key=lambda x: (x.line, x.severity.value)):
                    severity_label = self.SEVERITY_EMOJI[issue.severity]
                    lines.append(f"**{severity_label}** Line {issue.line}: {issue.title}")
                    lines.append(f"  - {issue.description}")
                    if issue.suggestion:
                        lines.append(f"  - *Suggestion:* {issue.suggestion}")
                    if issue.code_snippet:
                        lines.append(f"  ```")
                        lines.append(f"  {issue.code_snippet}")
                        lines.append(f"  ```")
                    lines.append("")

        # Files reviewed
        lines.append("## Files Reviewed\n")
        for file_path in result.files_reviewed:
            lines.append(f"- {file_path}")

        return "\n".join(lines)

    def generate_text(self, result: ReviewResult) -> str:
        """Generate plain text report.

        Args:
            result: Review result.

        Returns:
            Plain text report.
        """
        lines = []

        # Header
        lines.append("=" * 60)
        lines.append("CODE REVIEW REPORT")
        lines.append("=" * 60)
        lines.append("")

        # Summary
        status = "PASSED" if result.passed else "NEEDS ATTENTION"
        lines.append(f"Status: {status}")
        lines.append(f"Score: {result.score}/100")
        lines.append(f"Files Reviewed: {len(result.files_reviewed)}")
        lines.append(f"Total Issues: {len(result.issues)}")
        lines.append("")

        if result.issues:
            lines.append("-" * 60)
            lines.append("ISSUES")
            lines.append("-" * 60)

            for issue in sorted(result.issues, key=lambda x: (x.severity.value, x.file_path, x.line)):
                lines.append("")
                lines.append(f"[{issue.severity.value.upper()}] {issue.title}")
                lines.append(f"  File: {issue.file_path}:{issue.line}")
                lines.append(f"  {issue.description}")
                if issue.suggestion:
                    lines.append(f"  Suggestion: {issue.suggestion}")
                if issue.code_snippet:
                    lines.append(f"  Code: {issue.code_snippet}")

        lines.append("")
        lines.append("=" * 60)

        return "\n".join(lines)

    def generate_json(self, result: ReviewResult) -> dict:
        """Generate JSON report.

        Args:
            result: Review result.

        Returns:
            Dictionary suitable for JSON serialization.
        """
        return result.to_dict()

    def generate_github_comments(self, result: ReviewResult) -> list[dict]:
        """Generate GitHub PR comment format.

        Args:
            result: Review result.

        Returns:
            List of comment dictionaries for GitHub API.
        """
        comments = []

        for issue in result.issues:
            # Skip info-level issues for PR comments
            if issue.severity == Severity.INFO:
                continue

            body = f"**{self.SEVERITY_EMOJI[issue.severity]}** {issue.title}\n\n"
            body += f"{issue.description}\n\n"
            if issue.suggestion:
                body += f"*Suggestion:* {issue.suggestion}"

            comments.append({
                "path": issue.file_path,
                "line": issue.line,
                "body": body,
            })

        return comments

    def generate_summary(self, result: ReviewResult) -> str:
        """Generate a brief summary.

        Args:
            result: Review result.

        Returns:
            Brief summary string.
        """
        if not result.issues:
            return "No issues found. Code looks good!"

        parts = []

        if result.critical_count:
            parts.append(f"{result.critical_count} critical")
        if result.high_count:
            parts.append(f"{result.high_count} high severity")
        if result.medium_count:
            parts.append(f"{result.medium_count} medium")

        if not parts:
            return f"Found {result.low_count + result.info_count} minor issues. Overall looking good."

        return f"Found issues: {', '.join(parts)}. Review recommended."

    def generate_inline_report(self, result: ReviewResult) -> str:
        """Generate inline report for terminal display.

        Args:
            result: Review result.

        Returns:
            Formatted string for terminal.
        """
        if not result.issues:
            return "No issues found."

        lines = []
        current_file = None

        for issue in sorted(result.issues, key=lambda x: (x.file_path, x.line)):
            if issue.file_path != current_file:
                if current_file:
                    lines.append("")
                current_file = issue.file_path
                lines.append(f"{current_file}:")

            severity = issue.severity.value[0].upper()  # C/H/M/L/I
            lines.append(f"  {issue.line:4d} [{severity}] {issue.title}")

        lines.append("")
        lines.append(f"Total: {len(result.issues)} issues (Score: {result.score}/100)")

        return "\n".join(lines)

    def _group_by_file(self, issues: list[ReviewIssue]) -> dict[str, list[ReviewIssue]]:
        """Group issues by file path."""
        grouped = {}
        for issue in issues:
            if issue.file_path not in grouped:
                grouped[issue.file_path] = []
            grouped[issue.file_path].append(issue)
        return grouped

    def _group_by_category(self, issues: list[ReviewIssue]) -> dict[str, list[ReviewIssue]]:
        """Group issues by category."""
        grouped = {}
        for issue in issues:
            category = issue.category.value
            if category not in grouped:
                grouped[category] = []
            grouped[category].append(issue)
        return grouped


# Convenience function
def generate_report(result: ReviewResult, format: str = "markdown") -> str:
    """Generate a review report.

    Args:
        result: Review result.
        format: Output format (markdown, text, json).

    Returns:
        Formatted report string.
    """
    reporter = ReviewReporter()

    if format == "markdown":
        return reporter.generate_markdown(result)
    elif format == "text":
        return reporter.generate_text(result)
    elif format == "json":
        import json
        return json.dumps(reporter.generate_json(result), indent=2)
    elif format == "summary":
        return reporter.generate_summary(result)
    elif format == "inline":
        return reporter.generate_inline_report(result)
    else:
        return reporter.generate_markdown(result)
