"""Markdown export utilities for XAI explanations.

Copyright 2026 Maggioli SPA
Licensed under Apache 2.0
Author: Costas Vrioni (costas.vrioni@maggioli.gr)
"""

from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any, Optional

import xai_suite
from xai_suite.utils.visualization import save_local_explanation


@dataclass
class MarkdownExportConfig:
    """Configuration for Markdown export."""

    output_path: str
    title: str = "XAI Explanation Report"
    top_n_features: Optional[int] = None
    image_format: str = "svg"
    include_shap: bool = True
    include_lime: bool = True
    include_narrative: bool = True
    include_insights: bool = True
    include_compliance: bool = True
    figure_dpi: int = 100


class MarkdownExporter:
    """Exports XAI explanation results to Markdown format."""

    def __init__(self, config: MarkdownExportConfig):
        """
        Initialize the Markdown exporter.

        Args:
            config: Export configuration.
        """
        self.config = config
        self._output_path = Path(config.output_path)
        self._output_dir = self._output_path.parent
        self._base_name = self._output_path.stem

    def export(self, result: dict[str, Any]) -> str:
        """
        Export explanation result to Markdown file.

        Args:
            result: The explanation result dictionary from XAIOrchestrator.

        Returns:
            Path to the generated Markdown file.
        """
        sections = []

        # Header
        sections.append(self._generate_header())

        # Executive Summary (narrative)
        if self.config.include_narrative and "narrative" in result:
            narrative_section = self._generate_narrative_section(result["narrative"])
            if narrative_section:
                sections.append(narrative_section)

        # Feature Importance Analysis
        feature_sections = self._generate_feature_sections(result)
        if feature_sections:
            sections.append(feature_sections)

        # Actionable Insights
        if self.config.include_insights and "insights" in result:
            insights_section = self._generate_insights_section(result["insights"])
            if insights_section:
                sections.append(insights_section)

        # EU AI Act Compliance
        if self.config.include_compliance and "compliance" in result:
            compliance_section = self._generate_compliance_section(result["compliance"])
            if compliance_section:
                sections.append(compliance_section)

        # Footer
        sections.append(self._generate_footer())

        # Write to file
        content = "\n".join(sections)
        self._output_path.parent.mkdir(parents=True, exist_ok=True)
        self._output_path.write_text(content)

        return str(self._output_path)

    def _generate_header(self) -> str:
        """Generate the Markdown header section."""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        version = xai_suite.__version__

        return f"""# {self.config.title}

**Generated:** {timestamp}
**XAI Suite Version:** {version}

---"""

    def _generate_narrative_section(self, narrative: dict[str, Any]) -> Optional[str]:
        """Generate the executive summary/narrative section."""
        text = narrative.get("text")
        if not text:
            return None

        return f"""
## Executive Summary

{text}

---"""

    def _generate_feature_sections(self, result: dict[str, Any]) -> Optional[str]:
        """Generate feature importance analysis sections."""
        sections = []
        has_content = False

        sections.append("\n## Feature Importance Analysis")

        # SHAP section
        if self.config.include_shap and "shap" in result:
            shap_section = self._generate_explainer_section(
                result["shap"], "SHAP", "shap"
            )
            if shap_section:
                sections.append(shap_section)
                has_content = True

        # LIME section
        if self.config.include_lime and "lime" in result:
            lime_section = self._generate_explainer_section(
                result["lime"], "LIME", "lime"
            )
            if lime_section:
                sections.append(lime_section)
                has_content = True

        if not has_content:
            return None

        sections.append("\n---")
        return "\n".join(sections)

    def _generate_explainer_section(
        self, explanation: dict[str, Any], display_name: str, method_key: str
    ) -> Optional[str]:
        """Generate a section for a specific explainer."""
        feature_names = explanation.get("feature_names", [])
        importance_scores = explanation.get("importance_scores", [])
        feature_values = explanation.get("feature_values")

        if not feature_names or not importance_scores:
            return None

        # Prepare data with optional top_n filtering
        data = list(zip(feature_names, importance_scores))
        if feature_values and len(feature_values) == len(feature_names):
            data = [
                (fn, fs, fv)
                for fn, fs, fv in zip(feature_names, importance_scores, feature_values)
            ]
            has_values = True
        else:
            has_values = False

        # Sort by absolute importance (descending)
        if has_values:
            data.sort(key=lambda x: abs(x[1]), reverse=True)
        else:
            data.sort(key=lambda x: abs(x[1]), reverse=True)

        # Apply top_n filter
        if self.config.top_n_features is not None:
            data = data[: self.config.top_n_features]

        # Build table
        lines = [f"\n### {display_name} Analysis\n"]

        if has_values:
            lines.append("| Feature | Value | Contribution |")
            lines.append("|---------|-------|--------------|")
            for fn, score, val in data:
                lines.append(f"| {fn} | {val:.4g} | {score:+.4f} |")
        else:
            lines.append("| Feature | Contribution |")
            lines.append("|---------|--------------|")
            for fn, score in data:
                lines.append(f"| {fn} | {score:+.4f} |")

        # Generate and save image
        image_filename = f"{self._base_name}_{method_key}_importance.{self.config.image_format}"
        image_path = self._output_dir / image_filename

        # Ensure output directory exists for image
        self._output_dir.mkdir(parents=True, exist_ok=True)

        save_local_explanation(
            explanation,
            str(image_path),
            dpi=self.config.figure_dpi,
            top_n=self.config.top_n_features,
        )

        lines.append(f"\n![{display_name} Feature Importance]({image_filename})")

        return "\n".join(lines)

    def _generate_insights_section(self, insights: list[dict[str, Any]]) -> Optional[str]:
        """Generate the actionable insights section."""
        if not insights:
            return None

        lines = ["\n## Actionable Insights\n"]

        for i, insight in enumerate(insights, 1):
            priority = insight.get("priority", "medium")
            priority_emoji = {"high": "🔴", "medium": "🟡", "low": "🟢"}.get(
                priority, "⚪"
            )
            insight_type = insight.get("type", "info")
            title = insight.get("title", f"Insight {i}")
            description = insight.get("description", "")
            action = insight.get("action", "")
            related_features = insight.get("related_features", [])

            lines.append(f"### {priority_emoji} {title}")
            lines.append(f"**Type:** {insight_type} | **Priority:** {priority}\n")

            if description:
                lines.append(f"{description}\n")

            if action:
                lines.append(f"**Recommended Action:** {action}\n")

            if related_features:
                features_str = ", ".join(f"`{f}`" for f in related_features)
                lines.append(f"**Related Features:** {features_str}\n")

        lines.append("---")
        return "\n".join(lines)

    def _generate_compliance_section(
        self, compliance: dict[str, Any]
    ) -> Optional[str]:
        """Generate the EU AI Act compliance section."""
        articles = compliance.get("applicable_articles", [])
        if not articles:
            return None

        audit_id = compliance.get("audit_id", "N/A")

        lines = ["\n## EU AI Act Compliance\n"]
        lines.append(f"**Audit ID:** {audit_id}\n")
        lines.append("| Article | Title | Relevance |")
        lines.append("|---------|-------|-----------|")

        for article in articles:
            art_id = article.get("article", "")
            art_title = article.get("title", "")
            relevance = article.get("relevance", "")
            lines.append(f"| {art_id} | {art_title} | {relevance} |")

        lines.append("\n---")
        return "\n".join(lines)

    def _generate_footer(self) -> str:
        """Generate the Markdown footer."""
        version = xai_suite.__version__
        return f"\n*Generated by XAI Suite v{version}*"


def export_to_markdown(
    result: dict[str, Any],
    output_path: str,
    title: str = "XAI Explanation Report",
    top_n_features: Optional[int] = None,
    image_format: str = "svg",
    include_shap: bool = True,
    include_lime: bool = True,
    include_narrative: bool = True,
    include_insights: bool = True,
    include_compliance: bool = True,
    figure_dpi: int = 100,
) -> str:
    """
    Export XAI explanation result to a Markdown file.

    This is a convenience function that creates a MarkdownExporter with the
    provided configuration and exports the result.

    Args:
        result: The explanation result dictionary from XAIOrchestrator.
        output_path: Path for the output Markdown file.
        title: Title for the report. Defaults to "XAI Explanation Report".
        top_n_features: If provided, only include top N features by importance.
        image_format: Image format for visualizations ('svg' or 'png').
            Defaults to 'svg'.
        include_shap: Whether to include SHAP analysis. Defaults to True.
        include_lime: Whether to include LIME analysis. Defaults to True.
        include_narrative: Whether to include narrative section. Defaults to True.
        include_insights: Whether to include insights section. Defaults to True.
        include_compliance: Whether to include compliance section. Defaults to True.
        figure_dpi: DPI for saved figures. Defaults to 100.

    Returns:
        Path to the generated Markdown file.

    Example:
        >>> result = orchestrator.explain(instance)
        >>> export_to_markdown(result, "report.md", title="Security Analysis")
        'report.md'
    """
    config = MarkdownExportConfig(
        output_path=output_path,
        title=title,
        top_n_features=top_n_features,
        image_format=image_format,
        include_shap=include_shap,
        include_lime=include_lime,
        include_narrative=include_narrative,
        include_insights=include_insights,
        include_compliance=include_compliance,
        figure_dpi=figure_dpi,
    )

    exporter = MarkdownExporter(config)
    return exporter.export(result)
