"""Report generation — usage reports from session data."""

from __future__ import annotations

import csv
import io
import json
from datetime import datetime, timedelta, timezone

from nestdx.session.storage import SessionStore
from nestdx.utils.console import console, format_duration

from rich.table import Table


class ReportGenerator:
    """Generate usage reports from session store data."""

    def __init__(self, store: SessionStore) -> None:
        self._store = store

    def generate(
        self,
        *,
        days: int = 30,
        group_by: str | None = None,
        fmt: str = "rich",
    ) -> str | None:
        """Generate a usage report.

        Args:
            days: Include sessions from the last N days.
            group_by: "tool" or "engineer". None for overall summary.
            fmt: "rich" (prints to terminal, returns None), "json", or "csv".

        Returns:
            Formatted string for json/csv, or None for rich (printed directly).
        """
        since = datetime.now(timezone.utc) - timedelta(days=days)
        stats = self._store.aggregate(group_by="tool" if group_by == "tool" else None, since=since)

        if group_by == "engineer":
            engineer_groups = self._aggregate_by_engineer(since=since)
            stats["groups"] = engineer_groups

        if fmt == "json":
            return self._format_json(stats, days=days, group_by=group_by)
        elif fmt == "csv":
            return self._format_csv(stats, group_by=group_by)
        else:
            self._format_rich(stats, days=days, group_by=group_by)
            return None

    def _aggregate_by_engineer(self, *, since: datetime) -> list[dict]:
        """Group sessions by git author (from git snapshot branch is not enough,
        so we use the session data directly)."""
        sessions = self._store.query(since=since, limit=10000)

        engineer_stats: dict[str, dict] = {}
        for s in sessions:
            # Use git snapshot branch as a proxy, or "unknown"
            author = "unknown"
            if s.git_snapshot and s.git_snapshot.branch:
                author = s.git_snapshot.branch.split("/")[0] if "/" in s.git_snapshot.branch else "local"

            if author not in engineer_stats:
                engineer_stats[author] = {
                    "engineer": author,
                    "sessions": 0,
                    "total_duration": 0.0,
                    "total_tokens": 0,
                    "total_cost": 0.0,
                    "violations_count": 0,
                }
            engineer_stats[author]["sessions"] += 1
            engineer_stats[author]["total_duration"] += s.duration_seconds or 0
            engineer_stats[author]["total_tokens"] += s.total_tokens
            engineer_stats[author]["total_cost"] += s.total_cost
            engineer_stats[author]["violations_count"] += len(s.violations)

        return sorted(engineer_stats.values(), key=lambda g: g["sessions"], reverse=True)

    def _format_rich(self, stats: dict, *, days: int, group_by: str | None) -> None:
        """Print a Rich-formatted report to the terminal."""
        console.print(f"\n[bold]NestDX Usage Report[/bold] (last {days} days)\n")

        # Overall summary
        console.print(f"  Sessions:     {stats['total_sessions']}")
        console.print(f"  Duration:     {format_duration(stats['total_duration'])}")
        console.print(f"  Files changed:{stats['file_changes_count']:>5}")
        console.print(f"  Violations:   {stats['violations_count']}")
        if stats["total_tokens"] > 0:
            console.print(f"  Tokens:       {stats['total_tokens']:,}")
        if stats["total_cost"] > 0:
            console.print(f"  Cost:         ${stats['total_cost']:.2f}")

        groups = stats.get("groups")
        if groups:
            console.print()
            label = "Tool" if group_by == "tool" else "Engineer" if group_by == "engineer" else "Group"

            table = Table(show_header=True, header_style="bold")
            table.add_column(label)
            table.add_column("Sessions", justify="right")
            table.add_column("Duration", justify="right")
            table.add_column("Tokens", justify="right")
            table.add_column("Cost", justify="right")
            table.add_column("Violations", justify="right")

            for g in groups:
                name = g.get("tool") or g.get("engineer") or g.get("status", "unknown")
                table.add_row(
                    name,
                    str(g["sessions"]),
                    format_duration(g["total_duration"]),
                    f"{g['total_tokens']:,}" if g["total_tokens"] else "-",
                    f"${g['total_cost']:.2f}" if g["total_cost"] else "-",
                    str(g["violations_count"]),
                )

            console.print(table)

    def _format_json(self, stats: dict, *, days: int, group_by: str | None) -> str:
        """Return a JSON-formatted report."""
        report = {
            "report": "nestdx-usage",
            "days": days,
            "group_by": group_by,
            **stats,
        }
        return json.dumps(report, indent=2)

    def _format_csv(self, stats: dict, *, group_by: str | None) -> str:
        """Return a CSV-formatted report."""
        output = io.StringIO()
        groups = stats.get("groups")

        if groups:
            label = "tool" if group_by == "tool" else "engineer" if group_by == "engineer" else "group"
            fieldnames = [label, "sessions", "total_duration", "total_tokens", "total_cost", "violations_count"]
            writer = csv.DictWriter(output, fieldnames=fieldnames)
            writer.writeheader()
            for g in groups:
                row = {
                    label: g.get("tool") or g.get("engineer") or g.get("status", "unknown"),
                    "sessions": g["sessions"],
                    "total_duration": f"{g['total_duration']:.1f}",
                    "total_tokens": g["total_tokens"],
                    "total_cost": f"{g['total_cost']:.2f}",
                    "violations_count": g["violations_count"],
                }
                writer.writerow(row)
        else:
            fieldnames = ["total_sessions", "total_duration", "total_tokens", "total_cost", "violations_count", "file_changes_count"]
            writer = csv.DictWriter(output, fieldnames=fieldnames)
            writer.writeheader()
            writer.writerow({
                "total_sessions": stats["total_sessions"],
                "total_duration": f"{stats['total_duration']:.1f}",
                "total_tokens": stats["total_tokens"],
                "total_cost": f"{stats['total_cost']:.2f}",
                "violations_count": stats["violations_count"],
                "file_changes_count": stats["file_changes_count"],
            })

        return output.getvalue()
