"""Export plugin — export task results in multiple formats."""

from __future__ import annotations

import csv
import io
import json
import time
from typing import Any

from agent_scout.plugins.base import Plugin, PluginParam, ToolSpec


def _export_json(data: dict[str, Any]) -> str:
    return json.dumps(data, indent=2, default=str)


def _export_markdown(data: dict[str, Any]) -> str:
    lines: list[str] = []
    title = data.get("title", "AgentScout Export")
    lines.append(f"# {title}")
    lines.append("")
    lines.append(f"*Exported on {time.strftime('%Y-%m-%d %H:%M')}*")
    lines.append("")

    if summary := data.get("summary"):
        lines.append("## Summary")
        lines.append("")
        lines.append(summary)
        lines.append("")

    if results := data.get("results"):
        lines.append("## Results")
        lines.append("")
        if isinstance(results, list):
            for item in results:
                if isinstance(item, dict):
                    lines.append(f"- **{item.get('name', 'Item')}**: {item.get('value', '')}")
                else:
                    lines.append(f"- {item}")
        elif isinstance(results, dict):
            for k, v in results.items():
                lines.append(f"- **{k}**: {v}")
        else:
            lines.append(str(results))
        lines.append("")

    if table := data.get("comparison_table"):
        lines.append("## Comparison")
        lines.append("")
        lines.extend(_dict_list_to_md_table(table))
        lines.append("")

    if steps := data.get("steps"):
        lines.append("## Steps Taken")
        lines.append("")
        for i, step in enumerate(steps, 1):
            lines.append(f"{i}. {step}")
        lines.append("")

    return "\n".join(lines)


def _dict_list_to_md_table(rows: list[dict[str, Any]]) -> list[str]:
    """Convert a list of dicts to a markdown table."""
    if not rows:
        return []
    headers = list(rows[0].keys())
    lines = [
        "| " + " | ".join(headers) + " |",
        "| " + " | ".join("---" for _ in headers) + " |",
    ]
    for row in rows:
        cells = [str(row.get(h, "")) for h in headers]
        lines.append("| " + " | ".join(cells) + " |")
    return lines


def _export_csv(data: dict[str, Any]) -> str:
    rows = data.get("comparison_table") or data.get("results")
    if not rows:
        return ""

    if isinstance(rows, list) and rows and isinstance(rows[0], dict):
        buf = io.StringIO()
        writer = csv.DictWriter(buf, fieldnames=rows[0].keys())
        writer.writeheader()
        writer.writerows(rows)
        return buf.getvalue()

    # Flat list
    buf = io.StringIO()
    writer = csv.writer(buf)
    writer.writerow(["item"])
    for r in rows:
        writer.writerow([str(r)])
    return buf.getvalue()


def _export_html(data: dict[str, Any]) -> str:
    title = data.get("title", "AgentScout Report")
    summary = data.get("summary", "")
    lines = [
        "<!DOCTYPE html>",
        "<html lang='en'>",
        "<head>",
        f"  <title>{title}</title>",
        "  <meta charset='utf-8'>",
        "  <meta name='viewport' content='width=device-width, initial-scale=1'>",
        "  <style>",
        "    body { font-family: 'Plus Jakarta Sans', system-ui, sans-serif;"
        " max-width: 800px; margin: 2rem auto; padding: 0 1rem; color: #333; }",
        "    h1 { color: #e05a3a; }",
        "    table { width: 100%; border-collapse: collapse; margin: 1rem 0; }",
        "    th, td { padding: 0.5rem; border: 1px solid #ddd; text-align: left; }",
        "    th { background: #f5f5f5; }",
        "    .meta { color: #888; font-size: 0.9rem; }",
        "    .step { padding: 0.5rem 0; border-bottom: 1px solid #eee; }",
        "  </style>",
        "</head>",
        "<body>",
        f"  <h1>{title}</h1>",
        f"  <p class='meta'>Exported on {time.strftime('%Y-%m-%d %H:%M')} by AgentScout</p>",
    ]

    if summary:
        lines.append(f"  <p>{summary}</p>")

    if results := data.get("results"):
        lines.append("  <h2>Results</h2>")
        lines.append("  <ul>")
        if isinstance(results, list):
            for item in results:
                if isinstance(item, dict):
                    name = item.get("name", "")
                    val = item.get("value", "")
                    lines.append(f"    <li><strong>{name}</strong>: {val}</li>")
                else:
                    lines.append(f"    <li>{item}</li>")
        elif isinstance(results, dict):
            for k, v in results.items():
                lines.append(f"    <li><strong>{k}</strong>: {v}</li>")
        lines.append("  </ul>")

    if table := data.get("comparison_table"):
        lines.append("  <h2>Comparison</h2>")
        lines.append("  <table>")
        if table:
            headers = list(table[0].keys())
            lines.append("    <tr>" + "".join(f"<th>{h}</th>" for h in headers) + "</tr>")
            for row in table:
                cells = "".join(f"<td>{row.get(h, '')}</td>" for h in headers)
                lines.append(f"    <tr>{cells}</tr>")
        lines.append("  </table>")

    if steps := data.get("steps"):
        lines.append("  <h2>Steps Taken</h2>")
        for i, step in enumerate(steps, 1):
            lines.append(f"  <div class='step'>{i}. {step}</div>")

    lines.append("</body>")
    lines.append("</html>")

    return "\n".join(lines)


class ExporterPlugin(Plugin):
    """Export task results in JSON, Markdown, CSV, or HTML.

    Supports exporting task results, comparison tables,
    conversation history, and generating shareable standalone HTML reports.
    """

    @property
    def name(self) -> str:
        return "exporter"

    @property
    def description(self) -> str:
        return "Export task results in multiple formats (JSON, Markdown, CSV, HTML)"

    def get_tools(self) -> list[ToolSpec]:
        return [
            ToolSpec(
                name="export",
                description=(
                    "Export data in a specified format. Provide the data as a JSON object "
                    "with optional keys: title, summary, results, comparison_table, steps."
                ),
                parameters=[
                    PluginParam(
                        name="format",
                        description="Output format: json, markdown, csv, or html",
                        required=True,
                    ),
                    PluginParam(
                        name="data",
                        description="Data to export (JSON object)",
                        param_type="object",
                        required=True,
                    ),
                    PluginParam(
                        name="save_path",
                        description="File path to save (optional, returns content if omitted)",
                    ),
                ],
            ),
        ]

    async def execute(self, tool_name: str, tool_input: dict[str, Any]) -> str:
        if tool_name != "export":
            return f"Unknown tool: {tool_name}"

        fmt = tool_input.get("format", "json").lower()
        data = tool_input.get("data", {})
        save_path = tool_input.get("save_path", "")

        if isinstance(data, str):
            try:
                data = json.loads(data)
            except json.JSONDecodeError:
                return "Error: Invalid JSON data"

        if not data:
            return "Error: No data provided"

        exporters = {
            "json": _export_json,
            "markdown": _export_markdown,
            "md": _export_markdown,
            "csv": _export_csv,
            "html": _export_html,
        }

        exporter = exporters.get(fmt)
        if not exporter:
            return f"Error: Unsupported format '{fmt}'. Use: json, markdown, csv, or html"

        content = exporter(data)
        if not content:
            return "Error: Export produced no content"

        if save_path:
            try:
                with open(save_path, "w") as f:
                    f.write(content)
                return f"Exported to {save_path} ({len(content)} bytes)"
            except OSError as e:
                return f"Error saving to {save_path}: {e}"

        return content
