"""
HTML report generator for code review results.

This module provides utilities for generating HTML-formatted reports
from code review results with syntax highlighting for code snippets.
"""

from typing import Any, Dict, List, Optional
import os
from datetime import datetime

from pygments import highlight
from pygments.lexers import get_lexer_by_name, guess_lexer, TextLexer
from pygments.formatters import HtmlFormatter
from pygments.util import ClassNotFound

from vaahai.reporting.formats import OutputFormat

# CSS styles for the HTML report
HTML_STYLE = """
body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    line-height: 1.6;
    color: #333;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}
h1, h2, h3, h4 {
    color: #2c3e50;
    margin-top: 1.5em;
    margin-bottom: 0.5em;
}
h1 {
    border-bottom: 2px solid #3498db;
    padding-bottom: 10px;
}
h2 {
    border-bottom: 1px solid #bdc3c7;
    padding-bottom: 5px;
}
table {
    border-collapse: collapse;
    width: 100%;
    margin: 20px 0;
}
th, td {
    padding: 12px 15px;
    text-align: left;
    border-bottom: 1px solid #ddd;
}
th {
    background-color: #f8f9fa;
}
tr:hover {
    background-color: #f5f5f5;
}
.severity-critical {
    color: #e74c3c;
    font-weight: bold;
}
.severity-high {
    color: #e67e22;
}
.severity-medium {
    color: #f39c12;
}
.severity-low {
    color: #27ae60;
}
.severity-info {
    color: #3498db;
}
.code-block {
    border: 1px solid #ddd;
    border-radius: 4px;
    margin: 10px 0;
}
.footer {
    text-align: center;
    margin-top: 30px;
    font-size: 0.9em;
    color: #7f8c8d;
    border-top: 1px solid #ecf0f1;
    padding-top: 20px;
}
"""

# Pygments CSS styles
PYGMENTS_STYLE = HtmlFormatter(style='vs').get_style_defs('.highlight')


class HTMLReporter:
    """
    Generates HTML-formatted reports from code review results.
    
    This class converts the review results into a well-structured HTML
    document with syntax highlighting for code snippets using Pygments.
    """
    
    def __init__(self, results: Dict[str, Any]):
        """
        Initialize the HTML reporter.
        
        Args:
            results: Dictionary containing the review results
        """
        self.results = results
        
    def generate_report(self) -> str:
        """
        Generate an HTML report from the review results.
        
        Returns:
            HTML-formatted string containing the report
        """
        if self.results.get("status") == "error":
            return self._generate_error_report()
        
        # Start building the report
        report = []
        
        # Add HTML header with CSS styles
        report.append(self._generate_html_header())
        
        # Add report header
        report.append(self._generate_header())
        
        # Add summary section
        report.append(self._generate_summary())
        
        # Add key findings section
        report.append(self._generate_key_findings())
        
        # Add recommendations section
        report.append(self._generate_recommendations())
        
        # Add statistics section
        report.append(self._generate_statistics())
        
        # Add issues by file section
        report.append(self._generate_issues_by_file())
        
        # Add footer
        report.append(self._generate_footer())
        
        # Close HTML document
        report.append("</body></html>")
        
        return "\n".join(report)
    
    def _generate_error_report(self) -> str:
        """Generate a report for error results."""
        return f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VaahAI Code Review Error</title>
    <style>
    {HTML_STYLE}
    </style>
</head>
<body>
    <h1>Code Review Error</h1>
    
    <h2>Error Details</h2>
    
    <p><strong>Status:</strong> Error</p>
    <p><strong>Message:</strong> {self.results.get('message', 'Unknown error')}</p>
    
    <div class="footer">
        <p>Generated by VaahAI Code Review</p>
    </div>
</body>
</html>
"""
    
    def _generate_html_header(self) -> str:
        """Generate the HTML document header with CSS styles."""
        return f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>VaahAI Code Review Report</title>
    <style>
    {HTML_STYLE}
    {PYGMENTS_STYLE}
    </style>
</head>
<body>
"""
    
    def _generate_header(self) -> str:
        """Generate the report header."""
        now = datetime.now()
        date_str = now.strftime("%Y-%m-%d %H:%M:%S")
        
        return f"""<h1>VaahAI Code Review Report</h1>
<p><em>Generated on: {date_str}</em></p>
"""
    
    def _generate_summary(self) -> str:
        """Generate the summary section."""
        total_issues = self.results.get("total_issues", 0)
        message = self.results.get("message", "")
    
        # Get file information if available
        file_results = self.results.get("file_results", [])
        num_files = len(file_results) if file_results else 1
    
        html = "<h2>Summary</h2>\n"
        html += f"<p>{message}</p>\n<ul>\n"
        
        if file_results:
            html += f"<li><strong>Files Reviewed:</strong> {num_files}</li>\n"
            html += f"<li><strong>Total Issues:</strong> {total_issues}</li>\n"
        else:
            # Handle different result formats (dict or list)
            results = self.results.get("results", {})
            file_path = "Unknown file"
            
            if isinstance(results, dict):
                # If results is a dict of step results
                if results:
                    # Get the first step result
                    first_step = next(iter(results.values()))
                    file_path = first_step.get("file_path", "Unknown file")
            elif isinstance(results, list) and results:
                # If results is a list of step results
                file_path = results[0].get("file_path", "Unknown file")
            
            html += f"<li><strong>File:</strong> {file_path}</li>\n"
            html += f"<li><strong>Total Issues:</strong> {total_issues}</li>\n"
        
        # Add progress information if available
        progress = self.results.get("progress", {})
        if progress:
            total_steps = progress.get("total_steps", 0)
            completed_steps = progress.get("completed_steps", 0)
            failed_steps = progress.get("failed_steps", 0)
            
            html += f"<li><strong>Review Steps:</strong> {completed_steps}/{total_steps} completed"
            if failed_steps > 0:
                html += f", {failed_steps} failed"
            html += "</li>\n"
        
        html += "</ul>\n"
        return html
    
    def _generate_key_findings(self) -> str:
        """Generate the key findings section."""
        key_findings = self.results.get("key_findings", [])
        
        if not key_findings:
            return ""
        
        html = "<h2>Key Findings</h2>\n<ul>\n"
        
        for finding in key_findings:
            finding_type = finding.get("type", "")
            severity = finding.get("severity", "")
            count = finding.get("count", 0)
            message = finding.get("message", "")
            
            if finding_type == "severity" and severity:
                severity_class = f"severity-{severity.lower()}"
                severity_emoji = self._get_severity_emoji(severity)
                html += f'<li><span class="{severity_class}">{severity_emoji} <strong>{severity.title()}:</strong></span> {message}</li>\n'
            else:
                html += f"<li><strong>Issue ({count} occurrences):</strong> {message}</li>\n"
        
        html += "</ul>\n"
        return html
    
    def _generate_recommendations(self) -> str:
        """Generate the recommendations section."""
        recommendations = self.results.get("recommendations", [])
        
        if not recommendations:
            return ""
        
        html = "<h2>Actionable Recommendations</h2>\n<ol>\n"
        
        for recommendation in recommendations:
            html += f"<li>{recommendation}</li>\n"
        
        html += "</ol>\n"
        return html
    
    def _generate_statistics(self) -> str:
        """Generate the statistics section."""
        statistics = self.results.get("statistics", {})
        
        if not statistics:
            return ""
        
        html = "<h2>Statistics</h2>\n"
        
        # File statistics
        total_files = statistics.get("total_files", 0)
        files_with_issues = statistics.get("files_with_issues", 0)
        files_with_issues_percentage = statistics.get("files_with_issues_percentage", 0)
        
        html += "<h3>File Statistics</h3>\n<ul>\n"
        html += f"<li><strong>Total Files:</strong> {total_files}</li>\n"
        html += f"<li><strong>Files with Issues:</strong> {files_with_issues} ({files_with_issues_percentage:.1f}%)</li>\n"
        html += f"<li><strong>Average Issues per File:</strong> {statistics.get('issues_per_file', 0):.2f}</li>\n"
        html += "</ul>\n"
        
        # Issues by severity
        issues_by_severity = statistics.get("issues_by_severity", {})
        
        if issues_by_severity:
            html += "<h3>Issues by Severity</h3>\n"
            html += "<table>\n"
            html += "<tr><th>Severity</th><th>Count</th><th>Percentage</th></tr>\n"
            
            total_issues = statistics.get("total_issues", 0)
            
            for severity, count in issues_by_severity.items():
                if total_issues > 0:
                    percentage = (count / total_issues) * 100
                else:
                    percentage = 0
                
                severity_class = f"severity-{severity.lower()}"
                severity_emoji = self._get_severity_emoji(severity)
                html += f'<tr><td class="{severity_class}">{severity_emoji} {severity.title()}</td><td>{count}</td><td>{percentage:.1f}%</td></tr>\n'
            
            html += "</table>\n"
        
        # Issues by category
        issues_by_category = statistics.get("issues_by_category", {})
        
        if issues_by_category:
            html += "<h3>Issues by Category</h3>\n"
            html += "<table>\n"
            html += "<tr><th>Category</th><th>Count</th><th>Percentage</th></tr>\n"
            
            total_issues = statistics.get("total_issues", 0)
            
            for category, count in issues_by_category.items():
                if total_issues > 0:
                    percentage = (count / total_issues) * 100
                else:
                    percentage = 0
                
                html += f"<tr><td>{category.replace('_', ' ').title()}</td><td>{count}</td><td>{percentage:.1f}%</td></tr>\n"
            
            html += "</table>\n"
        
        # Most common issues
        most_common_issues = statistics.get("most_common_issues", [])
        
        if most_common_issues:
            html += "<h3>Most Common Issues</h3>\n<ul>\n"
            
            for issue, count in most_common_issues:
                html += f"<li><strong>({count} occurrences):</strong> {issue}</li>\n"
            
            html += "</ul>\n"
        
        return html
    
    def _generate_issues_by_file(self) -> str:
        """Generate the issues by file section."""
        # For directory reviews
        file_results = self.results.get("file_results", [])
    
        if file_results:
            html = "<h2>Issues by File</h2>\n"
    
            for file_result in file_results:
                file_path = file_result.get("file_path", "")
                file_issues = file_result.get("total_issues", 0)
    
                if file_issues > 0:
                    file_name = os.path.basename(file_path)
                    html += f"<h3>{file_name} ({file_issues} issues)</h3>\n"
    
                    # Get the results for this file
                    results = file_result.get("results", [])
                    html += self._format_issues(results, file_path)
    
            return html
        
        # For single file reviews
        results = self.results.get("results", [])
    
        if not results:
            return ""
    
        html = "<h2>Detailed Issues</h2>\n"
        
        # Handle different result formats (dict or list)
        file_path = ""
        if isinstance(results, dict):
            # If results is a dict of step results
            html += "<h3>Issues by Step</h3>\n"
            for step_id, step_result in results.items():
                if step_result.get("issues"):
                    html += f"<h4>{step_id}</h4>\n<ul>\n"
                    for issue in step_result.get("issues", []):
                        html += f"<li>{issue}</li>\n"
                    html += "</ul>\n"
            return html
        elif isinstance(results, list) and results:
            # If results is a list of step results
            file_path = results[0].get("file_path", "")
        
        file_name = os.path.basename(file_path) if file_path else "Unknown file"
        html += f"<h3>{file_name}</h3>\n"
        
        html += self._format_issues(results, file_path)
        
        return html
    
    def _format_issues(self, results: List[Dict[str, Any]], file_path: str) -> str:
        """Format issues for a specific file with syntax highlighting."""
        html = ""
        
        for result in results:
            step_name = result.get("step_name", "")
            step_category = result.get("step_category", "").replace("_", " ").title()
            step_severity = result.get("step_severity", "").lower()
            issues = result.get("issues", [])
            
            if not issues:
                continue
            
            severity_class = f"severity-{step_severity}"
            severity_emoji = self._get_severity_emoji(step_severity)
            html += f'<h4><span class="{severity_class}">{severity_emoji} {step_name}</span> ({step_category})</h4>\n<ul>\n'
            
            for issue in issues:
                line = issue.get("line", "")
                message = issue.get("message", "")
                code = issue.get("code", "")
                
                if line:
                    html += f"<li><strong>Line {line}:</strong> {message}</li>\n"
                else:
                    html += f"<li>{message}</li>\n"
                
                if code:
                    # Apply syntax highlighting to the code
                    highlighted_code = self._highlight_code(code, file_path)
                    html += f'<div class="code-block">{highlighted_code}</div>\n'
            
            html += "</ul>\n"
        
        return html
    
    def _highlight_code(self, code: str, file_path: str) -> str:
        """Apply syntax highlighting to code using Pygments."""
        try:
            # Try to guess the lexer based on the file extension
            if file_path:
                file_ext = os.path.splitext(file_path)[1].lstrip('.')
                if file_ext:
                    try:
                        lexer = get_lexer_by_name(file_ext)
                    except ClassNotFound:
                        # If the extension doesn't match a lexer, try to guess from content
                        lexer = guess_lexer(code)
                else:
                    lexer = guess_lexer(code)
            else:
                # If no file path, try to guess from content
                lexer = guess_lexer(code)
        except ClassNotFound:
            # Fallback to plain text
            lexer = TextLexer()
        
        # Format the code with HTML formatter
        formatter = HtmlFormatter(linenos=True, cssclass="highlight")
        return highlight(code, lexer, formatter)
    
    def _generate_footer(self) -> str:
        """Generate the report footer."""
        return '<div class="footer"><p>Generated by VaahAI Code Review</p></div>'
    
    def _get_severity_emoji(self, severity: str) -> str:
        """Get an emoji for the given severity level."""
        severity = severity.lower()
        
        if severity == "critical":
            return "🔴"
        elif severity == "high":
            return "🟠"
        elif severity == "medium":
            return "🟡"
        elif severity == "low":
            return "🟢"
        else:
            return "ℹ️"


def generate_html_report(results: Dict[str, Any]) -> str:
    """
    Generate an HTML report from review results with syntax highlighting.
    
    Args:
        results: Dictionary containing the review results
        
    Returns:
        HTML-formatted string containing the report
    """
    reporter = HTMLReporter(results)
    return reporter.generate_report()
