"""Report generator for domain analysis results."""

import os
from datetime import datetime
from pathlib import Path
from typing import Any, Dict

from rich.console import Console

from .safety_rating import calculate_domain_safety_rating


class ReportGenerator:
    """Generate markdown reports from domain analysis results."""

    def __init__(self, output_dir: str = "reports"):
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(exist_ok=True)
        self.console = Console()

    def generate_report(
        self, domain: str, results: Dict[str, Any], include_screenshot: bool = True, pdf: bool = False
    ) -> str:
        """
        Generate a markdown (and optionally PDF) report for the domain.
        Returns the path to the markdown report.
        """
        # Generate markdown content
        safety_rating = calculate_domain_safety_rating(results)
        markdown_content = self._create_report_content(domain, results, safety_rating, include_screenshot)
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        md_filename = f"{domain}_report_{timestamp}.md"
        md_path = os.path.join(self.output_dir, md_filename)
        with open(md_path, "w", encoding="utf-8") as f:
            f.write(markdown_content)

        if pdf:
            try:
                from markdown_pdf import MarkdownPdf, Section
            except ImportError:
                print("markdown-pdf is not installed. Please run 'pip install markdown-pdf' to enable PDF export.")
                return md_path
            pdf_filename = f"{domain}_report_{timestamp}.pdf"
            pdf_path = os.path.join(self.output_dir, pdf_filename)
            pdf_doc = MarkdownPdf()
            pdf_doc.meta["title"] = f"AlexScan Report: {domain}"
            pdf_doc.add_section(Section(markdown_content, toc=False))
            pdf_doc.save(pdf_path)
            print(f"PDF report generated: {pdf_path}")
        return md_path

    def _create_report_content(
        self,
        domain: str,
        results: Dict[str, Any],
        safety_rating: Dict[str, Any],
        include_screenshot: bool,
    ) -> str:
        """Create the markdown report content."""
        content = []

        # Professional Header
        content.append("# ALEXSCAN DOMAIN SECURITY ANALYSIS REPORT")
        content.append("")
        content.append("---")
        content.append("")
        content.append("- **Generated by:** AlexScan Security Analysis Platform")
        content.append("- **Report Type:** Comprehensive Domain Security Assessment")
        content.append("- **Analysis Date:** " + datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC"))
        content.append("- **Report Version:** 1.0")
        content.append("")
        content.append("---")
        content.append("")

        # Report Header
        content.append(f"# Domain Analysis Report: {domain}")
        content.append(f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}")
        content.append("")
        classification = safety_rating["classification"].upper()

        # Executive Summary
        content.append("## EXECUTIVE SUMMARY")
        content.append("")

        if "llm_summary_results" in results and results["llm_summary_results"].get("llm_summary", {}).get("summary"):
            content.append(results["llm_summary_results"]["llm_summary"]["summary"])
        else:
            content.append(
                f"This domain has been classified as **{classification}** based on comprehensive security analysis."
            )

        content.append("")

        # DOMAIN SAFETY ASSESSMENT - Always at the top
        content.append("## DOMAIN SAFETY ASSESSMENT")
        content.append("")

        # Overall Domain Safety Rating
        content.append("### DOMAIN SAFETY ASSESSMENT")
        content.append("")

        overall_score = safety_rating["overall_score"]
        percentage_score = safety_rating["percentage_score"]

        content.append(f"**Domain:** {domain}")
        content.append("")
        content.append(f"**Analyzers Run:** {len(safety_rating['component_scores'])}")
        content.append("")
        content.append(f"**OVERALL SAFETY SCORE:** {overall_score}/10 ({percentage_score}%)")
        content.append("")
        content.append(f"**CLASSIFICATION:** {classification.upper()}")
        content.append("")

        # Component Scores
        content.append("### COMPONENT SAFETY SCORES")
        content.append("")

        content.append("| Analyzer | Safety Score | Status |")
        content.append("|----------|--------------|--------|")

        component_scores = safety_rating["component_scores"]
        for analyzer, score in component_scores.items():
            analyzer_name = analyzer.replace("_", " ").title()
            if score >= 7.0:
                status = "Good"
            elif score >= 5.0:
                status = "Moderate"
            elif score >= 3.0:
                status = "Poor"
            else:
                status = "Critical"
            content.append(f"| {analyzer_name} | {score}/10 | {status} |")

        content.append("")

        # Safety Rating Thresholds
        content.append("### Safety Rating Thresholds")
        content.append("")
        content.append("- **70-100% (7.0-10.0)**: Safe")
        content.append("- **50-70% (5.0-7.0)**: Likely Unsafe")
        content.append("- **30-50% (3.0-5.0)**: Likely Malicious")
        content.append("- **0-30% (0.0-3.0)**: Unsafe (high risk)")
        content.append("")

        # Domain Categorization
        content.append("## DOMAIN CATEGORIZATION")
        content.append("")

        if "hierarchical_classification_results" in results:
            categorization_data = results["hierarchical_classification_results"]

            if categorization_data.get("classification"):
                classification = categorization_data["classification"]

                content.append("### Content Classification")
                content.append("")
                content.append("| Field | Value |")
                content.append("|-------|-------|")
                content.append(f"| Primary Category | {classification.get('primary_category', 'Unknown')} |")
                content.append(f"| Subcategory | {classification.get('subcategory', 'Unknown')} |")
                content.append(f"| Confidence | {classification.get('confidence', 0)}% |")
                content.append("")

                # Evidence
                if classification.get("evidence"):
                    content.append("### Classification Evidence")
                    content.append("")
                    content.append(classification["evidence"])
                    content.append("")

            # Errors if any
            if categorization_data.get("errors"):
                content.append("### Categorization Errors")
                content.append("")
                for error in categorization_data["errors"]:
                    content.append(f"- {error}")
                content.append("")
        else:
            content.append("### Content Classification")
            content.append("")
            content.append("| Field | Value |")
            content.append("|-------|-------|")
            content.append("| Primary Category | Unknown |")
            content.append("| Subcategory | Unknown |")
            content.append("| Confidence | 0% |")
            content.append("")
            content.append("*Categorization not performed*")
            content.append("")

        # DNS Analysis
        if "dns_results" in results:
            content.append("## DNS ANALYSIS")
            content.append("")

            dns_data = results["dns_results"]
            if "records" in dns_data:
                content.append("### DNS Records")
                content.append("")

                dns_records = dns_data["records"]
                for record_type, record_info in dns_records.items():
                    if record_info and "values" in record_info:
                        values = record_info["values"]
                        if values:
                            content.append(f"**{record_type.upper()} Records:**")
                            content.append("")
                            content.append("| Record | Value |")
                            content.append("|--------|-------|")
                            for i, value in enumerate(values, 1):
                                content.append(f"| {record_type} #{i} | {value} |")
                            content.append("")

            # Add errors if any
            if dns_data.get("errors"):
                content.append("### DNS Errors")
                content.append("")
                content.append("| Error |")
                content.append("|-------|")
                for error in dns_data["errors"]:
                    content.append(f"| {error} |")
                content.append("")

        # WHOIS Analysis
        if "whois_results" in results:
            content.append("## WHOIS ANALYSIS")
            content.append("")

            whois_data = results["whois_results"]
            if "whois_data" in whois_data:
                content.append("### Registration Information")
                content.append("")

                whois_info = whois_data["whois_data"]
                content.append("| Field | Value |")
                content.append("|-------|-------|")
                content.append(f"| Registrar | {whois_info.get('registrar', 'Unknown')} |")
                content.append(f"| Creation Date | {whois_info.get('creation_date', 'Unknown')} |")
                content.append(f"| Expiry Date | {whois_info.get('expiry_date', 'Unknown')} |")
                content.append(f"| Organization | {whois_info.get('organization', 'Unknown')} |")
                content.append(f"| Country | {whois_info.get('country', 'Unknown')} |")
                content.append("")

        # SSL/TLS Analysis
        if "ssl_results" in results:
            content.append("## SSL/TLS ANALYSIS")
            content.append("")

            ssl_data = results["ssl_results"]
            if "ssl_data" in ssl_data:
                content.append("### Certificate Information")
                content.append("")

                ssl_info = ssl_data["ssl_data"]
                content.append("| Field | Value |")
                content.append("|-------|-------|")
                content.append(f"| Issuer | {ssl_info.get('issuer', 'Unknown')} |")
                content.append(f"| Valid From | {ssl_info.get('valid_from', 'Unknown')} |")
                content.append(f"| Valid To | {ssl_info.get('valid_to', 'Unknown')} |")
                content.append(f"| Is Expired | {ssl_info.get('is_expired', 'Unknown')} |")
                content.append(f"| Days Until Expiry | {ssl_info.get('days_until_expiry', 'Unknown')} |")
                content.append("")

        # Blocklist Analysis
        if "blocklist_results" in results:
            content.append("## BLOCKLIST ANALYSIS")
            content.append("")

            blocklist_data = results["blocklist_results"]
            if "blocklist_status" in blocklist_data:
                content.append("### Summary")
                content.append("")

                summary = blocklist_data.get("summary", {})
                content.append(f"**Lists Checked:** {summary.get('total_lists_checked', 0)}")
                content.append(f"**Listed:** {summary.get('listed_count', 0)}")
                content.append(f"**Clean:** {summary.get('clean_count', 0)}")
                content.append("")

                content.append("### Detailed Results")
                content.append("")
                content.append("| Blocklist | Status | Description |")
                content.append("|-----------|--------|-------------|")
                for source, data in blocklist_data["blocklist_status"].items():
                    status = "Listed" if data.get("listed") else "Clean"
                    description = data.get("description", "")
                    content.append(f"| {source} | {status} | {description} |")
                content.append("")

        # Whitelist Analysis
        if "whitelist_results" in results:
            content.append("## WHITELIST ANALYSIS")
            content.append("")

            whitelist_data = results["whitelist_results"]
            if "whitelist_status" in whitelist_data:
                content.append("### Summary")
                content.append("")

                summary = whitelist_data.get("summary", {})
                content.append(f"**Lists Checked:** {summary.get('total_lists_checked', 0)}")
                content.append(f"**Whitelisted:** {summary.get('whitelisted_count', 0)}")
                content.append(f"**Not Whitelisted:** {summary.get('not_whitelisted_count', 0)}")
                content.append("")

                content.append("### Detailed Results")
                content.append("")
                content.append("| Whitelist | Status | Description |")
                content.append("|-----------|--------|-------------|")
                for source, data in whitelist_data["whitelist_status"].items():
                    status = "Whitelisted" if data.get("whitelisted") else "Not Whitelisted"
                    description = data.get("description", "")
                    content.append(f"| {source} | {status} | {description} |")
                content.append("")

        # DGA Analysis
        if "dga_results" in results:
            content.append("## DGA ANALYSIS")
            content.append("")
            dga_data = results["dga_results"]

            if "dga_analysis" in dga_data:
                dga_info = dga_data["dga_analysis"]
                content.append("### Detection Results")
                content.append("")
                content.append("| Field | Value |")
                content.append("|-------|-------|")
                content.append(f"| Classification | {dga_info.get('classification', 'Unknown')} |")
                content.append(f"| DGA Probability | {dga_info.get('dga_probability', 0)} |")
                content.append(f"| Risk Level | {dga_info.get('risk_level', 'Unknown')} |")
                content.append("")

                # Show traditional analysis
                if dga_info.get("traditional_analysis"):
                    traditional = dga_info["traditional_analysis"]
                    content.append("### Traditional Analysis")
                    content.append("")
                    content.append("| Field | Value |")
                    content.append("|-------|-------|")
                    content.append(f"| Classification | {traditional.get('classification', 'Unknown')} |")
                    content.append(f"| Confidence | {traditional.get('confidence', 'Unknown')} |")
                    content.append("")

                # Show LLM analysis if available
                if dga_info.get("llm_analysis") and "error" not in dga_info["llm_analysis"]:
                    llm = dga_info["llm_analysis"]
                    content.append("### LLM Analysis")
                    content.append("")
                    content.append("| Field | Value |")
                    content.append("|-------|-------|")
                    content.append(f"| Classification | {llm.get('classification', 'Unknown')} |")
                    content.append(f"| Confidence | {llm.get('confidence', 'Unknown')}% |")
                    content.append("")

                    if llm.get("reasoning"):
                        content.append("#### LLM Reasoning")
                        content.append("")
                        content.append(llm["reasoning"])
                        content.append("")

                    if llm.get("key_indicators"):
                        content.append("#### Key Indicators")
                        content.append("")
                        for indicator in llm["key_indicators"]:
                            content.append(f"- {indicator}")
                        content.append("")

                    if llm.get("risk_factors"):
                        content.append("#### Risk Factors")
                        content.append("")
                        for factor in llm["risk_factors"]:
                            content.append(f"- {factor}")
                        content.append("")

                    if llm.get("legitimate_factors"):
                        content.append("#### Legitimate Factors")
                        content.append("")
                        for factor in llm["legitimate_factors"]:
                            content.append(f"- {factor}")
                        content.append("")
                elif dga_info.get("llm_analysis") and "error" in dga_info["llm_analysis"]:
                    content.append("### LLM Analysis")
                    content.append("")
                    content.append(f"*LLM analysis failed: {dga_info['llm_analysis']['error']}*")
                    content.append("")

        # HTTP Headers Analysis
        if "headers_results" in results:
            content.append("## HTTP SECURITY HEADERS")
            content.append("")
            headers_data = results["headers_results"]

            if "headers_data" in headers_data:
                content.append("### Security Assessment")
                content.append("")
                headers_info = headers_data["headers_data"]
                security_score = headers_info.get("security_score", 0)
                implemented = headers_info.get("implemented_security_headers", 0)
                total = headers_info.get("total_security_headers", 0)
                content.append(f"**Security Score:** {security_score}% ({implemented}/{total} headers implemented)")
                content.append("")

                # Implemented headers
                security_headers = headers_info.get("security_headers", {})
                if security_headers:
                    content.append("### Implemented Security Headers")
                    content.append("")
                    content.append("| Header | Assessment | Value |")
                    content.append("|--------|------------|-------|")
                    for header_name, header_info in security_headers.items():
                        assessment = header_info.get("assessment", "Unknown")
                        value = header_info.get("value", "")
                        content.append(f"| {header_name} | {assessment} | {value} |")
                    content.append("")

                # Missing headers
                missing_headers = headers_info.get("missing_headers", [])
                if missing_headers:
                    content.append("### Missing Security Headers")
                    content.append("")
                    for header in missing_headers:
                        content.append(f"- {header.get('name', '')}: {header.get('description', '')}")
                    content.append("")

        # Port Scanning Analysis
        if "ports_results" in results:
            content.append("## PORT SCANNING ANALYSIS")
            content.append("")
            ports_data = results["ports_results"]

            # IP Address
            ip_address = ports_data.get("ip_address", "")
            if ip_address:
                content.append(f"**IP Address:** {ip_address}")
                content.append("")

            # Scan Summary
            if "scan_summary" in ports_data:
                content.append("### Scan Summary")
                content.append("")
                summary = ports_data["scan_summary"]
                content.append("| Metric | Value |")
                content.append("|--------|-------|")
                content.append(f"| Total Ports Scanned | {summary.get('total_ports_scanned', 0)} |")
                content.append(f"| Open Ports Found | {summary.get('open_ports_count', 0)} |")
                content.append(f"| Vulnerabilities Found | {summary.get('vulnerabilities_found', 0)} |")
                content.append("")

            # Open Ports
            open_ports = ports_data.get("open_ports", [])
            if open_ports:
                content.append("### Open Ports and Services")
                content.append("")
                content.append("| Port | Service | Version | SSL |")
                content.append("|------|---------|---------|-----|")
                for port_info in open_ports:
                    port = port_info.get("port", "")
                    service = port_info.get("service", "")
                    version = port_info.get("version", "")
                    ssl = "Yes" if port_info.get("ssl_enabled") else "No"
                    content.append(f"| {port} | {service} | {version} | {ssl} |")
                content.append("")

            # Vulnerabilities
            vulnerabilities = ports_data.get("vulnerabilities", [])
            if vulnerabilities:
                content.append("### Detected Vulnerabilities")
                content.append("")
                content.append("| Severity | Type | Port | Description |")
                content.append("|----------|------|------|-------------|")
                for vuln in vulnerabilities:
                    severity = vuln.get("severity", "")
                    vuln_type = vuln.get("type", "")
                    port = vuln.get("port", "")
                    description = vuln.get("description", "")
                    content.append(f"| {severity} | {vuln_type} | {port} | {description} |")
                content.append("")

        # Screenshot
        if include_screenshot and "screenshot_results" in results:
            content.append("## SCREENSHOT")
            content.append("")
            screenshot_data = results["screenshot_results"]

            if screenshot_data.get("screenshot_data", {}).get("success"):
                screenshot_info = screenshot_data["screenshot_data"]

                # Add screenshot metadata
                content.append("### Screenshot Information")
                content.append("")
                content.append("| Field | Value |")
                content.append("|-------|-------|")
                content.append(f"| URL Captured | {screenshot_info.get('url_used', 'Unknown')} |")
                content.append(f"| File Size | {screenshot_info.get('file_size', 0)} bytes |")
                content.append(f"| Timestamp | {screenshot_info.get('timestamp', 'Unknown')} |")
                content.append(f"| Timeout | {screenshot_info.get('timeout', 'Unknown')} seconds |")
                content.append(f"| JavaScript Disabled | {screenshot_info.get('javascript_disabled', 'Unknown')} |")
                content.append("")

                # Include base64 image if available
                base64_data = screenshot_info.get("base64_data")
                if base64_data:
                    content.append("### Domain Screenshot")
                    content.append("")
                    content.append(f"![Domain Screenshot]({base64_data})")
                    content.append("")
                else:
                    # Fallback to file path if base64 not available
                    screenshot_path = screenshot_info.get("screenshot_path", "")
                    if screenshot_path and os.path.exists(screenshot_path):
                        content.append("### Domain Screenshot")
                        content.append("")
                        content.append(f"![Domain Screenshot]({screenshot_path})")
                        content.append("")
                    else:
                        content.append("*Screenshot captured but not available for display*")
                        content.append("")
            else:
                content.append("*Screenshot Not Available*")
                content.append("")

        # LLM Summary
        if "llm_summary_results" in results:
            content.append("## AI ANALYSIS SUMMARY")
            content.append("")
            llm_data = results["llm_summary_results"]

            # Get the actual LLM summary data from the nested structure
            llm_summary_data = llm_data.get("llm_summary", {})

            # Model information
            if llm_summary_data.get("model_used"):
                content.append(f"**AI Model Used:** {llm_summary_data['model_used']}")
                content.append("")

            # Classification and confidence
            if llm_summary_data.get("classification") or llm_summary_data.get("confidence_score"):
                content.append("### AI Classification")
                content.append("")
                if llm_summary_data.get("classification"):
                    content.append(f"**Classification:** {llm_summary_data['classification']}")
                if llm_summary_data.get("confidence_score"):
                    confidence = llm_summary_data["confidence_score"]
                    content.append(f"**Confidence Score:** {confidence:.1%}")
                content.append("")

            # Key findings summary
            if llm_summary_data.get("summary"):
                content.append("### Key Findings")
                content.append("")
                content.append(llm_summary_data["summary"])
                content.append("")

            # Detailed analysis
            if llm_summary_data.get("analysis"):
                content.append("### Detailed Analysis")
                content.append("")
                content.append(llm_summary_data["analysis"])
                content.append("")

            # Justification
            if llm_summary_data.get("justification"):
                content.append("### Risk Assessment Justification")
                content.append("")
                content.append(llm_summary_data["justification"])
                content.append("")

            # Recommendations and conclusion
            if llm_summary_data.get("conclusion"):
                content.append("### Recommendations & Conclusion")
                content.append("")
                content.append(llm_summary_data["conclusion"])
                content.append("")

            # Analysis metadata
            if llm_summary_data.get("analyzers_summarized") or llm_summary_data.get("website_content_analyzed"):
                content.append("### Analysis Metadata")
                content.append("")
                if llm_summary_data.get("analyzers_summarized"):
                    analyzers = [
                        analyzer.replace("_results", "").replace("_", " ").title()
                        for analyzer in llm_summary_data["analyzers_summarized"]
                    ]
                    content.append(f"**Analyzers Summarized:** {', '.join(analyzers)}")
                if llm_summary_data.get("website_content_analyzed"):
                    content.append(
                        f"**Website Content Analyzed:** {'Yes' if llm_summary_data['website_content_analyzed'] else 'No'}"
                    )
                content.append("")

            # Errors if any
            if llm_data.get("errors"):
                content.append("### Analysis Errors")
                content.append("")
                for error in llm_data["errors"]:
                    content.append(f"- {error}")
                content.append("")

        # Professional Footer
        content.append("---")
        content.append("")
        content.append("## REPORT METADATA")
        content.append("")
        content.append("| Field | Value |")
        content.append("|-------|-------|")
        content.append(f"| Report ID | {domain.replace('.', '_')}_{datetime.now().strftime('%Y%m%d_%H%M%S')} |")
        content.append("| Analysis Platform | AlexScan Security Analysis Platform |")
        content.append("| Report Version | 1.0 |")
        content.append(f"| Generated At | {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')} |")
        content.append(f"| Total Analyzers Run | {len(safety_rating['component_scores'])} |")
        content.append(f"| Overall Safety Score | {safety_rating['overall_score']}/10 |")
        content.append(f"| Classification | {safety_rating['classification']} |")
        content.append("")

        content.append("## DISCLAIMER")
        content.append("")
        content.append(
            "This report is generated by automated security analysis tools and should be used as part of a comprehensive security assessment. The findings presented are based on the analysis of publicly available information and may not represent the complete security posture of the domain."
        )
        content.append("")
        content.append("- This report is for informational purposes only")
        content.append("- Results should be validated by qualified security professionals")
        content.append("- The analysis is based on data available at the time of generation")
        content.append("- Security conditions may change over time")
        content.append("")

        content.append("## CONTACT INFORMATION")
        content.append("")
        content.append("For questions about this report or the AlexScan platform, please contact:")
        content.append("")
        content.append("- **Platform:** AlexScan Security Analysis Platform")
        content.append("- **Report Generated:** " + datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC"))
        content.append("- **Domain Analyzed:** " + domain)
        content.append("")

        content.append("---")
        content.append("")
        content.append("*End of Report*")
        content.append("")

        return "\n".join(content)
