"""Validation report generation in JSON and Markdown formats."""

from __future__ import annotations

import json
import time
from dataclasses import asdict, dataclass
from pathlib import Path

from orxaq.fabric.validation.metrics import ValidationMetrics


@dataclass
class ValidationReport:
    """Complete validation report."""

    algorithm: str
    variables_count: int
    data_rows: int
    metrics: ValidationMetrics
    timestamp: float
    predicted_edges: list[tuple[str, str]]
    true_edges: list[tuple[str, str]]

    def to_dict(self) -> dict:
        """Convert to JSON-serializable dict."""
        return {
            "algorithm": self.algorithm,
            "variables_count": self.variables_count,
            "data_rows": self.data_rows,
            "metrics": asdict(self.metrics),
            "timestamp": self.timestamp,
            "predicted_edges": [list(e) for e in self.predicted_edges],
            "true_edges": [list(e) for e in self.true_edges],
        }

    def to_json(self) -> str:
        """Serialize to JSON string."""
        return json.dumps(self.to_dict(), indent=2)

    def to_markdown(self) -> str:
        """Generate Markdown report."""
        m = self.metrics
        lines = [
            "# Validation Report",
            "",
            f"**Algorithm**: {self.algorithm}",
            f"**Variables**: {self.variables_count}",
            f"**Data rows**: {self.data_rows}",
            "",
            "## Metrics",
            "",
            "| Metric | Value |",
            "|--------|-------|",
            f"| SHD (Structural Hamming Distance) | {m.shd} |",
            f"| Precision | {m.precision:.3f} |",
            f"| Recall | {m.recall:.3f} |",
            f"| F1 Score | {m.f1:.3f} |",
            f"| Orientation Accuracy | {m.orientation_accuracy:.3f} |",
            f"| False Discovery Rate | {m.fdr:.3f} |",
            "",
            "## Edge Counts",
            "",
            f"- True edges: {m.total_true_edges}",
            f"- Predicted edges: {m.total_predicted_edges}",
            f"- True positives: {m.true_positives}",
            f"- False positives: {m.false_positives}",
            f"- False negatives: {m.false_negatives}",
            f"- Reversed edges: {m.reversed_edges}",
            "",
        ]
        return "\n".join(lines)


def generate_report(
    algorithm: str,
    variables_count: int,
    data_rows: int,
    metrics: ValidationMetrics,
    predicted_edges: list[tuple[str, str]],
    true_edges: list[tuple[str, str]],
) -> ValidationReport:
    """Create a validation report."""
    return ValidationReport(
        algorithm=algorithm,
        variables_count=variables_count,
        data_rows=data_rows,
        metrics=metrics,
        timestamp=time.time(),
        predicted_edges=predicted_edges,
        true_edges=true_edges,
    )


def save_report(report: ValidationReport, path: str | Path) -> None:
    """Save report to file (JSON or Markdown based on extension)."""
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)
    if path.suffix == ".md":
        path.write_text(report.to_markdown())
    else:
        path.write_text(report.to_json())
