#!/usr/bin/env python3
"""
report-generator.py
===================
Performance report generation and formatting for Digital Marketing Pro.

Generates structured markdown reports from metrics and converts them to
platform-specific formats (Slack Block Kit, HTML email, Google Sheets rows).

Storage: ~/.claude-marketing/brands/{slug}/reports/

Usage:
    python report-generator.py --brand acme --action generate-report --data '{"report_type": "weekly-pulse", "metrics": {"sessions": 12500}, "period": "2026-W07", "highlights": ["Traffic up 15%"], "recommendations": ["Increase ad spend"]}'
    python report-generator.py --brand acme --action format-slack --data '{"markdown": "# Weekly Pulse..."}'
    python report-generator.py --brand acme --action format-slack --id weekly-pulse-2026-W07
    python report-generator.py --brand acme --action format-email --id weekly-pulse-2026-W07
    python report-generator.py --brand acme --action format-sheets --data '{"metrics": {"sessions": 12500, "conversions": 340}}'
"""

import argparse
import json
import re
import sys
from datetime import datetime
from pathlib import Path

BRANDS_DIR = Path.home() / ".claude-marketing" / "brands"

VALID_REPORT_TYPES = [
    "weekly-pulse", "monthly-review", "quarterly-business-review", "custom",
]

REPORT_TITLES = {
    "weekly-pulse": "Weekly Performance Pulse",
    "monthly-review": "Monthly Performance Review",
    "quarterly-business-review": "Quarterly Business Review",
    "custom": "Custom Performance Report",
}


def get_brand_dir(slug):
    """Get and validate brand directory."""
    brand_dir = BRANDS_DIR / slug
    if not brand_dir.exists():
        return None, f"Brand '{slug}' not found. Run /dm:brand-setup first."
    return brand_dir, None


def _load_json(path, default=None):
    """Safely load a JSON file, returning default on missing/corrupt."""
    if default is None:
        default = {}
    if not path.exists():
        return default
    try:
        return json.loads(path.read_text(encoding="utf-8"))
    except (json.JSONDecodeError, OSError):
        return default


def _save_json(path, data):
    """Write JSON to a file."""
    path.write_text(json.dumps(data, indent=2), encoding="utf-8")


def _format_metric_value(value):
    """Human-friendly metric formatting."""
    if isinstance(value, float):
        if abs(value) < 1:
            return f"{value:.2%}"
        return f"{value:,.2f}"
    if isinstance(value, int):
        if value >= 1_000_000:
            return f"{value / 1_000_000:,.1f}M"
        if value >= 1_000:
            return f"{value / 1_000:,.1f}K"
        return f"{value:,}"
    return str(value)


def _build_markdown(report_type, period, metrics, highlights, recommendations, brand):
    """Build a structured markdown report."""
    title = REPORT_TITLES.get(report_type, "Performance Report")
    now = datetime.now().strftime("%Y-%m-%d %H:%M")
    lines = [
        f"# {title}",
        f"**Brand:** {brand} | **Period:** {period} | **Generated:** {now}",
        "",
        "---",
        "",
        "## Key Metrics",
        "",
        "| Metric | Value |",
        "|--------|-------|",
    ]
    for key, val in metrics.items():
        label = key.replace("_", " ").title()
        lines.append(f"| {label} | {_format_metric_value(val)} |")

    if highlights:
        lines += ["", "## Highlights", ""]
        for h in highlights:
            lines.append(f"- {h}")

    if recommendations:
        lines += ["", "## Recommendations", ""]
        for i, r in enumerate(recommendations, 1):
            lines.append(f"{i}. {r}")

    lines += ["", "---", f"*Report generated by Digital Marketing Pro*"]
    return "\n".join(lines)


def generate_report(slug, data):
    """Generate a structured markdown report and save it."""
    brand_dir, err = get_brand_dir(slug)
    if err:
        return {"error": err}

    report_type = data.get("report_type", "custom")
    if report_type not in VALID_REPORT_TYPES:
        return {"error": f"Invalid report_type '{report_type}'. Must be one of: {VALID_REPORT_TYPES}"}

    metrics = data.get("metrics", {})
    period = data.get("period", datetime.now().strftime("%Y-W%V"))
    highlights = data.get("highlights", [])
    recommendations = data.get("recommendations", [])

    markdown = _build_markdown(report_type, period, metrics, highlights, recommendations, slug)

    # Save report
    reports_dir = brand_dir / "reports"
    reports_dir.mkdir(exist_ok=True)
    report_id = f"{report_type}-{period}"
    report_record = {
        "report_id": report_id,
        "report_type": report_type,
        "period": period,
        "brand": slug,
        "created_at": datetime.now().isoformat(),
        "metrics": metrics,
        "highlights": highlights,
        "recommendations": recommendations,
        "markdown": markdown,
    }
    filepath = reports_dir / f"{report_id}.json"
    _save_json(filepath, report_record)

    return {
        "status": "generated",
        "report_id": report_id,
        "path": str(filepath),
        "markdown": markdown,
    }


def _load_report_markdown(slug, data=None, report_id=None):
    """Load markdown from --data or from a saved report by --id."""
    if data and data.get("markdown"):
        return data["markdown"], None

    if report_id:
        brand_dir, err = get_brand_dir(slug)
        if err:
            return None, err
        filepath = brand_dir / "reports" / f"{report_id}.json"
        report = _load_json(filepath, {})
        if not report:
            return None, f"Report '{report_id}' not found."
        return report.get("markdown", ""), None

    if data and data.get("report_id"):
        brand_dir, err = get_brand_dir(slug)
        if err:
            return None, err
        filepath = brand_dir / "reports" / f"{data['report_id']}.json"
        report = _load_json(filepath, {})
        if not report:
            return None, f"Report '{data['report_id']}' not found."
        return report.get("markdown", ""), None

    return None, "Provide --data with markdown content, or --id to load a saved report."


def format_slack(slug, data=None, report_id=None):
    """Convert markdown report to Slack Block Kit JSON."""
    md, err = _load_report_markdown(slug, data, report_id)
    if err:
        return {"error": err}

    blocks = []
    for line in md.split("\n"):
        line = line.strip()
        if not line:
            continue
        if line.startswith("# "):
            blocks.append({
                "type": "header",
                "text": {"type": "plain_text", "text": line[2:].strip()},
            })
        elif line == "---":
            blocks.append({"type": "divider"})
        elif line.startswith("| ") and "---" not in line:
            # Table row -> context block
            cells = [c.strip() for c in line.split("|") if c.strip()]
            text = " | ".join(cells)
            blocks.append({
                "type": "section",
                "text": {"type": "mrkdwn", "text": text},
            })
        elif line.startswith("## "):
            blocks.append({
                "type": "section",
                "text": {"type": "mrkdwn", "text": f"*{line[3:].strip()}*"},
            })
        elif line.startswith("- "):
            blocks.append({
                "type": "section",
                "text": {"type": "mrkdwn", "text": f"\u2022 {line[2:]}"},
            })
        elif re.match(r"^\d+\.\s", line):
            blocks.append({
                "type": "section",
                "text": {"type": "mrkdwn", "text": line},
            })
        elif line.startswith("**"):
            blocks.append({
                "type": "context",
                "elements": [{"type": "mrkdwn", "text": line}],
            })
        elif line.startswith("*") and line.endswith("*"):
            blocks.append({
                "type": "context",
                "elements": [{"type": "mrkdwn", "text": line}],
            })

    return {"format": "slack", "blocks": blocks}


def format_email(slug, data=None, report_id=None):
    """Convert markdown report to simple HTML email body."""
    md, err = _load_report_markdown(slug, data, report_id)
    if err:
        return {"error": err}

    html_parts = [
        '<!DOCTYPE html><html><head><meta charset="utf-8">',
        "<style>body{font-family:Arial,sans-serif;max-width:700px;margin:0 auto;padding:20px}",
        "table{border-collapse:collapse;width:100%}th,td{border:1px solid #ddd;padding:8px;text-align:left}",
        "th{background:#f4f4f4}h1{color:#333}h2{color:#555;border-bottom:1px solid #eee;padding-bottom:4px}",
        "li{margin:4px 0}hr{border:none;border-top:1px solid #ddd;margin:16px 0}</style></head><body>",
    ]

    in_table = False
    table_headers = []

    for line in md.split("\n"):
        stripped = line.strip()

        if stripped.startswith("# "):
            html_parts.append(f"<h1>{stripped[2:]}</h1>")
        elif stripped.startswith("## "):
            html_parts.append(f"<h2>{stripped[3:]}</h2>")
        elif stripped == "---":
            html_parts.append("<hr>")
        elif stripped.startswith("| ") and "---" in stripped:
            # Table separator row — skip
            continue
        elif stripped.startswith("| "):
            cells = [c.strip() for c in stripped.split("|") if c.strip()]
            if not in_table:
                in_table = True
                table_headers = cells
                html_parts.append("<table><thead><tr>")
                for c in cells:
                    html_parts.append(f"<th>{c}</th>")
                html_parts.append("</tr></thead><tbody>")
            else:
                html_parts.append("<tr>")
                for c in cells:
                    html_parts.append(f"<td>{c}</td>")
                html_parts.append("</tr>")
        else:
            if in_table:
                html_parts.append("</tbody></table>")
                in_table = False
            if stripped.startswith("- "):
                html_parts.append(f"<li>{stripped[2:]}</li>")
            elif re.match(r"^\d+\.\s", stripped):
                text = re.sub(r"^\d+\.\s", "", stripped)
                html_parts.append(f"<li>{text}</li>")
            elif stripped.startswith("**"):
                clean = stripped.replace("**", "<strong>", 1).replace("**", "</strong>", 1)
                html_parts.append(f"<p>{clean}</p>")
            elif stripped.startswith("*") and stripped.endswith("*"):
                html_parts.append(f"<p><em>{stripped[1:-1]}</em></p>")
            elif stripped:
                html_parts.append(f"<p>{stripped}</p>")

    if in_table:
        html_parts.append("</tbody></table>")

    html_parts.append("</body></html>")
    html = "\n".join(html_parts)

    return {"format": "email", "html": html}


def format_sheets(slug, data):
    """Convert metrics to tabular format for Google Sheets."""
    brand_dir, err = get_brand_dir(slug)
    if err:
        return {"error": err}

    metrics = data.get("metrics", {})
    if not metrics:
        return {"error": "No metrics provided in --data"}

    # Build header row + data row
    headers = ["Brand", "Generated"]
    values = [slug, datetime.now().strftime("%Y-%m-%d %H:%M")]

    for key, val in metrics.items():
        headers.append(key.replace("_", " ").title())
        values.append(val)

    return {
        "format": "sheets",
        "headers": headers,
        "rows": [values],
        "tabular": [headers, values],
    }


def main():
    parser = argparse.ArgumentParser(description="Report generation for Digital Marketing Pro")
    parser.add_argument("--brand", required=True, help="Brand slug")
    parser.add_argument("--action", required=True,
                        choices=["generate-report", "format-slack",
                                 "format-email", "format-sheets"],
                        help="Action to perform")
    parser.add_argument("--data", help="JSON data (metrics, markdown, etc.)")
    parser.add_argument("--id", dest="report_id", help="Report ID to load for formatting")
    args = parser.parse_args()

    if args.action == "generate-report":
        if not args.data:
            print(json.dumps({"error": "Provide --data with report JSON"}))
            sys.exit(1)
        try:
            data = json.loads(args.data)
        except json.JSONDecodeError:
            print(json.dumps({"error": "Invalid JSON in --data"}))
            sys.exit(1)
        result = generate_report(args.brand, data)

    elif args.action == "format-slack":
        data = None
        if args.data:
            try:
                data = json.loads(args.data)
            except json.JSONDecodeError:
                print(json.dumps({"error": "Invalid JSON in --data"}))
                sys.exit(1)
        result = format_slack(args.brand, data, args.report_id)

    elif args.action == "format-email":
        data = None
        if args.data:
            try:
                data = json.loads(args.data)
            except json.JSONDecodeError:
                print(json.dumps({"error": "Invalid JSON in --data"}))
                sys.exit(1)
        result = format_email(args.brand, data, args.report_id)

    elif args.action == "format-sheets":
        if not args.data:
            print(json.dumps({"error": "Provide --data with metrics JSON"}))
            sys.exit(1)
        try:
            data = json.loads(args.data)
        except json.JSONDecodeError:
            print(json.dumps({"error": "Invalid JSON in --data"}))
            sys.exit(1)
        result = format_sheets(args.brand, data)

    json.dump(result, sys.stdout, indent=2)
    print()


if __name__ == "__main__":
    main()
