"""Blog Draft Generator.

Generates Medium-style blog posts from project data: gaps, proposals,
drafts, stats, and the existing blog series narrative arc.

Usage:
    from ietf_analyzer.blog_drafts import BlogDraftGenerator
    gen = BlogDraftGenerator(config, db)
    result = gen.generate(topic="all analysis results", style="deep-dive")
"""

from __future__ import annotations

import json
from datetime import datetime, timezone
from pathlib import Path

from dotenv import load_dotenv
load_dotenv(Path(__file__).resolve().parent.parent.parent / ".env")
load_dotenv()

import anthropic
from rich.console import Console

from .config import Config
from .db import Database

console = Console()

BLOG_SYSTEM_PROMPT = """\
You are an expert technical writer producing Medium-style blog posts about IETF \
AI agent standardization. You write for a technical but non-specialist audience — \
engineers, product managers, and policy people who care about AI agent \
interoperability and safety.

Your writing style:
- Clear, opinionated, data-driven
- Use specific numbers and concrete examples (from the data provided)
- Short paragraphs, subheadings, occasional bold for emphasis
- Open with a hook that makes the reader care
- Include a "So what?" — why this matters for practitioners
- End with a forward-looking conclusion or call to action
- Tone: informed insider, not academic. Think Stratechery meets IETF.
- Use markdown formatting (## headings, **bold**, bullet lists, > blockquotes)
- Target length: 1500-3000 words depending on topic depth
- Include a suggested title and subtitle

Output the blog post in markdown. Start with a YAML front matter block:

```yaml
---
title: "The Title"
subtitle: "A compelling subtitle"
tags: [ietf, ai-agents, standards, ...]
estimated_reading_time: "X min read"
---
```

Then the full post body in markdown."""


CONTEXT_TEMPLATE = """\
## Project Data Context

You have access to the following data from our IETF AI Agent Standards analysis \
project (data as of March 2026):

### Corpus Overview
{overview}

### Gap Analysis ({gap_count} gaps identified)
{gaps}

### Draft Proposals ({proposal_count} proposals)
{proposals}

### Blog Series Context
The analysis is part of a planned 8-post blog series with the thesis:
"The IETF's AI agent standardization effort is the largest, fastest-growing, \
and most consequential standards race in a decade — but it is building the \
highways before the traffic lights."

Existing posts in the series:
{blog_series}

---

## User's Request

**Topic**: {topic}
**Style**: {style}
**Additional instructions**: {instructions}

Write the blog post now. Use the data above to support your arguments with \
specific numbers and examples. Do not invent statistics — only use what is \
provided in the context."""


STYLES = {
    "deep-dive": "Long-form deep dive (2500-3000 words). Thorough analysis with multiple sections.",
    "overview": "High-level overview (1500-2000 words). Accessible intro to a topic.",
    "opinion": "Opinionated take (1500-2000 words). Strong thesis, backed by data.",
    "listicle": "Structured list format (1500-2000 words). 'N things you should know about X'.",
    "comparison": "Comparative analysis (2000-2500 words). Side-by-side evaluation of approaches.",
    "series-post": "Part of the planned blog series (2000-2500 words). Fits the narrative arc.",
}


class BlogDraftGenerator:
    """Generate blog post drafts from project data."""

    def __init__(self, config: Config, db: Database):
        self.config = config
        self.db = db
        try:
            self.client = anthropic.Anthropic()
        except Exception:
            console.print(
                "[red bold]No Anthropic API key found.[/]\n"
                "Set ANTHROPIC_API_KEY environment variable or add to .env"
            )
            raise SystemExit(1)

    def _gather_overview(self) -> str:
        """Gather high-level corpus statistics."""
        total_drafts = self.db.conn.execute("SELECT count(*) FROM drafts").fetchone()[0]
        rated = self.db.conn.execute("SELECT count(*) FROM ratings WHERE false_positive = 0").fetchone()[0]
        authors = self.db.conn.execute("SELECT count(*) FROM authors").fetchone()[0]
        ideas = self.db.conn.execute("SELECT count(*) FROM ideas").fetchone()[0]
        gaps = self.db.conn.execute("SELECT count(*) FROM gaps").fetchone()[0]
        proposals = self.db.conn.execute("SELECT count(*) FROM proposals").fetchone()[0]

        # Category breakdown
        cat_rows = self.db.conn.execute(
            "SELECT categories FROM ratings WHERE false_positive = 0"
        ).fetchall()
        from collections import Counter
        cat_counts = Counter()
        for row in cat_rows:
            try:
                for cat in json.loads(row[0] or "[]"):
                    cat_counts[cat] += 1
            except (json.JSONDecodeError, TypeError):
                pass
        top_cats = cat_counts.most_common(10)
        cat_str = ", ".join(f"{c} ({n})" for c, n in top_cats)

        # Avg scores
        avg_row = self.db.conn.execute(
            "SELECT avg(novelty), avg(maturity), avg(relevance), avg(momentum), avg(overlap) "
            "FROM ratings WHERE false_positive = 0"
        ).fetchone()

        # Source breakdown
        src_rows = self.db.conn.execute(
            "SELECT source, count(*) FROM drafts GROUP BY source ORDER BY count(*) DESC"
        ).fetchall()
        src_str = ", ".join(f"{r[0]}: {r[1]}" for r in src_rows)

        return (
            f"- **{total_drafts} drafts** tracked ({rated} rated, rest pending)\n"
            f"- **{authors} authors**, **{ideas} ideas** extracted, **{gaps} gaps** identified\n"
            f"- **{proposals} draft proposals** in development\n"
            f"- Sources: {src_str}\n"
            f"- Top categories: {cat_str}\n"
            f"- Avg scores (1-5): novelty {avg_row[0]:.1f}, maturity {avg_row[1]:.1f}, "
            f"relevance {avg_row[2]:.1f}, momentum {avg_row[3]:.1f}, overlap {avg_row[4]:.1f}"
        )

    def _gather_gaps(self) -> str:
        """Gather gap data as context."""
        gaps = self.db.all_gaps()
        lines = []
        for g in gaps:
            lines.append(
                f"- **#{g['id']} [{g['severity'].upper()}]** {g['topic']} ({g['category']}): "
                f"{g['description'][:200]}"
            )
        return "\n".join(lines)

    def _gather_proposals(self) -> str:
        """Gather proposal summaries as context."""
        proposals = self.db.all_proposals()
        if not proposals:
            return "(No proposals yet)"
        lines = []
        for p in proposals:
            gap_refs = ", ".join(f"#{gid}" for gid in p.get("gap_ids", []))
            lines.append(
                f"- **{p['title']}** [{p['status']}] (gaps: {gap_refs or 'none'}): "
                f"{p.get('description', '')[:200]}"
            )
        return "\n".join(lines)

    def _gather_blog_series(self) -> str:
        """Gather existing blog series info."""
        blog_dir = Path(self.config.data_dir) / "reports" / "blog-series"
        if not blog_dir.exists():
            return "(No blog series found)"
        lines = []
        for f in sorted(blog_dir.glob("*.md")):
            if f.name == "data" or f.is_dir():
                continue
            # Read first few lines for title
            content = f.read_text(errors="replace")
            title_line = ""
            for line in content.split("\n"):
                if line.startswith("# "):
                    title_line = line[2:].strip()
                    break
            lines.append(f"- `{f.name}`: {title_line or f.stem}")
        return "\n".join(lines)

    def build_prompt(self, topic: str, style: str = "deep-dive",
                     instructions: str = "") -> str:
        """Build the full prompt with project data context."""
        overview = self._gather_overview()
        gaps_text = self._gather_gaps()
        proposals_text = self._gather_proposals()
        blog_series = self._gather_blog_series()

        gap_count = len(self.db.all_gaps())
        proposal_count = self.db.conn.execute("SELECT count(*) FROM proposals").fetchone()[0]

        style_desc = STYLES.get(style, STYLES["deep-dive"])

        return CONTEXT_TEMPLATE.format(
            overview=overview,
            gap_count=gap_count,
            gaps=gaps_text,
            proposal_count=proposal_count,
            proposals=proposals_text,
            blog_series=blog_series,
            topic=topic,
            style=f"{style} — {style_desc}",
            instructions=instructions or "(none)",
        )

    def generate(self, topic: str, style: str = "deep-dive",
                 instructions: str = "", cheap: bool = False) -> dict:
        """Generate a blog post draft.

        Returns dict with keys: title, subtitle, content, tags, usage.
        """
        console.print("[bold]Blog Draft Generator[/]")
        console.print(f"  Topic: {topic}")
        console.print(f"  Style: {style}")

        prompt = self.build_prompt(topic, style, instructions)
        model = self.config.claude_model_cheap if cheap else self.config.claude_model
        console.print(f"  Calling Claude ({model})...")

        resp = self.client.messages.create(
            model=model,
            max_tokens=16000,
            system=BLOG_SYSTEM_PROMPT,
            messages=[{"role": "user", "content": prompt}],
        )
        content = resp.content[0].text.strip()
        in_tok = resp.usage.input_tokens
        out_tok = resp.usage.output_tokens

        if "haiku" in model:
            cost = (in_tok * 0.8 + out_tok * 4) / 1_000_000
        else:
            cost = (in_tok * 3 + out_tok * 15) / 1_000_000

        console.print(
            f"  Tokens: {in_tok:,} in / {out_tok:,} out (~${cost:.3f})"
        )

        # Parse front matter if present
        title = topic
        subtitle = ""
        tags = []
        body = content

        if content.startswith("---") or content.startswith("```yaml"):
            # Try to extract YAML front matter
            try:
                if content.startswith("```yaml"):
                    fm_block = content.split("```")[1].replace("yaml\n", "", 1)
                    body = "```".join(content.split("```")[2:]).strip()
                else:
                    parts = content.split("---", 2)
                    if len(parts) >= 3:
                        fm_block = parts[1]
                        body = parts[2].strip()

                import re
                title_match = re.search(r'title:\s*"(.+?)"', fm_block)
                sub_match = re.search(r'subtitle:\s*"(.+?)"', fm_block)
                tag_match = re.search(r'tags:\s*\[(.+?)\]', fm_block)
                if title_match:
                    title = title_match.group(1)
                if sub_match:
                    subtitle = sub_match.group(1)
                if tag_match:
                    tags = [t.strip().strip('"').strip("'")
                            for t in tag_match.group(1).split(",")]
            except Exception:
                pass  # Fall through with raw content

        usage = {
            "model": model,
            "input_tokens": in_tok,
            "output_tokens": out_tok,
            "cost_usd": round(cost, 4),
        }

        return {
            "title": title,
            "subtitle": subtitle,
            "tags": tags,
            "content": body,
            "full_markdown": content,
            "usage": usage,
            "generated_at": datetime.now(timezone.utc).isoformat(),
        }
