"""Weekly review — synthesize the week's activity into patterns and trends.

CyrilXBT masterclass pattern: Sunday 7PM synthesis that identifies
recurring themes, tracks source performance, and generates insights.

Operates as a pure-rules aggregation layer — no AI synthesis needed.
"""
import sqlite3
from datetime import datetime, timedelta
from pathlib import Path
from collections import Counter


WEEKLY_TEMPLATE = """# Weekly Review — {week_start} to {week_end}

## SIGNAL SUMMARY

- **Total entries**: {total_entries}
- **New this week**: {new_this_week}
- **PUBLISH verdicts**: {publish_count}
- **WATCH verdicts**: {watch_count}
- **Average signal score**: {avg_score:.2f}

## TOP SOURCES (by entry count)

{sources_md}

## TOP CATEGORIES (by frequency)

{categories_md}

## SOURCE TIER BREAKDOWN

{tier_md}

## TRENDING THEMES

{trending_md}

## WEEK OVER WEEK COMPARISON

{wow_md}

## RECOMMENDATIONS

{recs_md}
"""


def get_connection(db_path: str) -> sqlite3.Connection:
    conn = sqlite3.connect(db_path)
    conn.row_factory = sqlite3.Row
    return conn


def _week_bounds(days_ago: int = 7) -> tuple:
    end = datetime.utcnow()
    start = end - timedelta(days=days_ago)
    return start, end


def fetch_weekly_stats(conn: sqlite3.Connection, days: int = 7) -> dict:
    """Aggregate weekly statistics from Athena entries."""
    start, end = _week_bounds(days)

    # Total entries
    cur = conn.execute("SELECT COUNT(*) as c FROM entries")
    total = cur.fetchone()["c"]

    # New this week
    cur = conn.execute(
        "SELECT COUNT(*) as c FROM entries WHERE first_seen >= ?",
        (start.isoformat(),),
    )
    new_this_week = cur.fetchone()["c"]

    # Verdict breakdown
    cur = conn.execute(
        "SELECT verdict, COUNT(*) as c FROM entries "
        "WHERE first_seen >= ? GROUP BY verdict",
        (start.isoformat(),),
    )
    verdicts = {row["verdict"]: row["c"] for row in cur}

    # Average signal score
    cur = conn.execute(
        "SELECT AVG(signal_score) as avg_score FROM entries WHERE first_seen >= ?",
        (start.isoformat(),),
    )
    avg_score = cur.fetchone()["avg_score"] or 0

    # Top sources
    cur = conn.execute(
        "SELECT source, COUNT(*) as c FROM entries "
        "WHERE first_seen >= ? GROUP BY source ORDER BY c DESC LIMIT 10",
        (start.isoformat(),),
    )
    top_sources = [(row["source"], row["c"]) for row in cur]

    # Top categories
    cur = conn.execute(
        "SELECT category_tags, COUNT(*) as c FROM entries "
        "WHERE first_seen >= ? AND category_tags IS NOT NULL AND category_tags != '' "
        "GROUP BY category_tags ORDER BY c DESC LIMIT 10",
        (start.isoformat(),),
    )
    top_categories = [(row["category_tags"], row["c"]) for row in cur]

    # Tier breakdown
    cur = conn.execute(
        "SELECT source_tier, COUNT(*) as c FROM entries "
        "WHERE first_seen >= ? GROUP BY source_tier ORDER BY source_tier",
        (start.isoformat(),),
    )
    tier_breakdown = {
        {1: "Tier 1 (High)", 2: "Tier 2 (Mid)", 3: "Tier 3 (Low)"}
        .get(row["source_tier"], f"Tier {row['source_tier']}"): row["c"]
        for row in cur
    }

    return {
        "week_start": start.strftime("%Y-%m-%d"),
        "week_end": end.strftime("%Y-%m-%d"),
        "total_entries": total,
        "new_this_week": new_this_week,
        "verdicts": verdicts,
        "publish_count": verdicts.get("PUBLISH", 0),
        "watch_count": verdicts.get("WATCH", 0),
        "avg_score": avg_score,
        "top_sources": top_sources,
        "top_categories": top_categories,
        "tier_breakdown": tier_breakdown,
    }


def _trending_themes(conn: sqlite3.Connection, days: int = 7) -> list:
    """Identify themes that appear more frequently this week vs last week."""
    start, end = _week_bounds(days)
    prev_start = start - timedelta(days=days)

    # This week's categories
    cur = conn.execute(
        "SELECT category_tags, COUNT(*) as c FROM entries "
        "WHERE first_seen >= ? AND first_seen < ? AND category_tags IS NOT NULL "
        "GROUP BY category_tags",
        (start.isoformat(), end.isoformat()),
    )
    this_week = {row["category_tags"]: row["c"] for row in cur}

    # Last week's categories
    cur = conn.execute(
        "SELECT category_tags, COUNT(*) as c FROM entries "
        "WHERE first_seen >= ? AND first_seen < ? AND category_tags IS NOT NULL "
        "GROUP BY category_tags",
        (prev_start.isoformat(), start.isoformat()),
    )
    last_week = {row["category_tags"]: row["c"] for row in cur}

    # Find trending (increased by 50%+ or new)
    trending = []
    for cat, count in this_week.items():
        prev_count = last_week.get(cat, 0)
        if prev_count == 0 and count >= 2:
            trending.append((cat, count, "NEW"))
        elif prev_count > 0 and count >= prev_count * 1.5:
            trending.append((cat, count, f"+{int((count - prev_count) / prev_count * 100)}%"))

    trending.sort(key=lambda x: x[1], reverse=True)
    return trending


def _generate_recommendations(stats: dict, trending: list) -> list:
    """Generate recommendations based on weekly patterns."""
    recs = []

    # Source diversity check
    if stats["top_sources"]:
        top_source_pct = stats["top_sources"][0][1] / max(stats["new_this_week"], 1) * 100
        if top_source_pct > 40:
            recs.append(
                f"⚠ High concentration from {stats['top_sources'][0][0]} "
                f"({top_source_pct:.0f}% of entries). Consider diversifying sources."
            )

    # PUBLISH rate
    if stats["publish_count"] == 0 and stats["new_this_week"] > 10:
        recs.append(
            "🔍 Zero PUBLISH verdicts despite "
            f"{stats['new_this_week']} new entries. "
            "Signal scoring may need recalibration."
        )

    # Trending themes
    if trending:
        recs.append(
            f"📈 Trending themes: {', '.join(t[0] for t in trending[:3])}. "
            "Consider deeper coverage."
        )

    # Score distribution
    if stats["avg_score"] < 3.0 and stats["new_this_week"] > 0:
        recs.append(
            f"📉 Average signal score ({stats['avg_score']:.2f}) is low. "
            "Check adapter signal_score assignments."
        )

    if not recs:
        recs.append("✅ System operating within normal parameters.")

    return recs


def generate_weekly(
    conn: sqlite3.Connection,
    days: int = 7,
    output_path: str | None = None,
) -> dict:
    """Generate a complete weekly review."""
    stats = fetch_weekly_stats(conn, days)
    trending = _trending_themes(conn, days)
    recommendations = _generate_recommendations(stats, trending)

    # Format sections
    top_sources_md = "\n".join(
        f"- **{s}**: {c} entries" for s, c in stats["top_sources"]
    ) or "_No sources._"

    top_cats_md = "\n".join(
        f"- **{c}**: {n} entries" for c, n in stats["top_categories"]
    ) or "_No categories._"

    tier_md = "\n".join(
        f"- **{label}**: {count}" for label, count in stats["tier_breakdown"].items()
    ) or "_No data._"

    trending_md = "\n".join(
        f"- **{t[0]}**: {t[1]} entries ({t[2]})" for t in trending
    ) or "_No trending themes detected._"

    # Week-over-week
    prev_count = stats["total_entries"] - stats["new_this_week"]
    if prev_count > 0:
        change = (stats["new_this_week"] - prev_count) / prev_count * 100
        wow = (
            f"New this week: {stats['new_this_week']} vs previous: {prev_count} "
            f"({change:+.0f}%)"
        )
    else:
        wow = f"First full week of data: {stats['new_this_week']} entries"

    recs_md = "\n".join(f"- {r}" for r in recommendations)

    review = {
        **stats,
        "trending": trending,
        "recommendations": recommendations,
    }
    review["markdown"] = WEEKLY_TEMPLATE.format(
        week_start=stats["week_start"],
        week_end=stats["week_end"],
        total_entries=stats["total_entries"],
        new_this_week=stats["new_this_week"],
        publish_count=stats["publish_count"],
        watch_count=stats["watch_count"],
        avg_score=stats["avg_score"],
        sources_md=top_sources_md,
        categories_md=top_cats_md,
        tier_md=tier_md,
        trending_md=trending_md,
        wow_md=wow,
        recs_md=recs_md,
    )

    if output_path:
        out = Path(output_path)
        out.parent.mkdir(parents=True, exist_ok=True)
        out.write_text(review["markdown"], encoding="utf-8")
        review["saved"] = str(out)

    return review


# ── CLI ──

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description="Generate Athena weekly review")
    parser.add_argument("--db", default="oracle.db")
    parser.add_argument("--days", type=int, default=7)
    parser.add_argument("--output", "-o", help="Output path for markdown review")
    parser.add_argument("--json", action="store_true", help="Output as JSON")

    args = parser.parse_args()
    conn = get_connection(args.db)

    try:
        review = generate_weekly(conn, days=args.days)
        if args.json:
            import json
            print(json.dumps({k: v for k, v in review.items() if k != "markdown"}, indent=2, default=str))
        elif args.output:
            generate_weekly(conn, days=args.days, output_path=args.output)
            print(f"Saved: {args.output}")
        else:
            print(review.get("markdown", "No review generated"))
    finally:
        conn.close()
