"""Artifact bundle — package run outputs for auditability and client sign-off."""

from __future__ import annotations

import json
import zipfile
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List


class ArtifactBundle:
    """Collect and package run artifacts (HTML, JSON, MD) into a single bundle."""

    def __init__(self, run_id: str, output_dir: Path | str = "data/artifacts"):
        self.run_id = run_id
        self.output_dir = Path(output_dir) / run_id
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.artifacts: List[Dict[str, str]] = []

    def add(self, name: str, content: Any, fmt: str = "json") -> Path:
        """Add an artifact to the bundle.

        Args:
            name: Artifact name (without extension).
            content: Content to write — dict/list for JSON, str for others.
            fmt: Format — json, md, html, txt.

        Returns:
            Path to the written file.
        """
        ext = {"json": ".json", "md": ".md", "html": ".html", "txt": ".txt"}.get(fmt, f".{fmt}")
        path = self.output_dir / f"{name}{ext}"

        if fmt == "json" and not isinstance(content, str):
            text = json.dumps(content, indent=2, default=str)
        else:
            text = str(content)

        path.write_text(text, encoding="utf-8")
        self.artifacts.append({"name": name, "path": str(path), "format": fmt})
        return path

    def generate_summary_html(self, run_summary: Dict[str, Any]) -> Path:
        """Generate an HTML summary report for the run.

        Delegates to ReportGenerator for rich reports when possible,
        falling back to a basic table if ReportGenerator is unavailable.

        Args:
            run_summary: Run summary dict from PlatformOrchestrator.

        Returns:
            Path to the generated HTML file.
        """
        try:
            from src.artifacts.report_generator import ReportGenerator
            report_path = ReportGenerator.from_run_result(run_summary, self.output_dir.parent)
            self.artifacts.append({"name": "run_report", "path": str(report_path), "format": "html"})
            return report_path
        except Exception:
            pass

        # Fallback: basic HTML report
        phases_html = ""
        for phase in run_summary.get("phases", []):
            status = phase.get("status", "unknown")
            colour = {
                "completed": "#28a745",
                "skipped": "#6c757d",
                "error": "#dc3545",
            }.get(status, "#ffc107")
            phases_html += (
                f'<tr><td>{phase.get("name", "")}</td>'
                f'<td style="color:{colour};font-weight:bold">{status}</td>'
                f'<td>{phase.get("duration_seconds", 0):.1f}s</td>'
                f'<td>{phase.get("error", "-")}</td></tr>\n'
            )

        html = f"""<!DOCTYPE html>
<html>
<head><title>DataBridge Run {self.run_id}</title>
<style>
  body {{ font-family: -apple-system, BlinkMacSystemFont, sans-serif; max-width: 900px; margin: 2em auto; }}
  table {{ border-collapse: collapse; width: 100%; }}
  th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
  th {{ background: #f4f4f4; }}
  h1 {{ color: #2c3e50; }}
</style></head>
<body>
<h1>DataBridge Platform Workflow Report</h1>
<p><strong>Run ID:</strong> {self.run_id}</p>
<p><strong>Status:</strong> {run_summary.get("status", "unknown")}</p>
<p><strong>Started:</strong> {run_summary.get("started_at", "N/A")}</p>
<p><strong>Duration:</strong> {run_summary.get("total_duration_seconds", 0):.1f}s</p>
<h2>Phase Results</h2>
<table>
<tr><th>Phase</th><th>Status</th><th>Duration</th><th>Error</th></tr>
{phases_html}
</table>
<h2>Artifacts</h2>
<ul>
{"".join(f'<li>{a["name"]} ({a["format"]})</li>' for a in self.artifacts)}
</ul>
<footer><p>Generated by DataBridge AI v0.42 at {datetime.utcnow().isoformat()}Z</p></footer>
</body></html>"""

        path = self.add("run_report", html, fmt="html")
        return path

    def generate_manifest(self) -> Path:
        """Generate a manifest file listing all artifacts in the bundle.

        Returns:
            Path to the manifest JSON file.
        """
        manifest = {
            "run_id": self.run_id,
            "generated_at": datetime.utcnow().isoformat() + "Z",
            "artifact_count": len(self.artifacts),
            "artifacts": self.artifacts,
            "output_dir": str(self.output_dir),
        }
        return self.add("manifest", manifest, fmt="json")

    def package(self) -> Path:
        """Create a zip archive of all artifacts in the bundle.

        Returns:
            Path to the zip file.
        """
        zip_path = self.output_dir.parent / f"{self.run_id}.zip"
        with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf:
            for art in self.artifacts:
                file_path = Path(art["path"])
                if file_path.exists():
                    zf.write(file_path, arcname=file_path.name)
        return zip_path
