"""Internet-Draft generation from gap analysis."""

from __future__ import annotations

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

from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, MofNCompleteColumn

from .config import Config
from .db import Database

console = Console()

OUTLINE_PROMPT = """\
You are writing an IETF Internet-Draft to address this gap in the AI/agent standardization landscape:

Gap: {gap_topic}
{gap_context}

Related existing drafts (for context, not to duplicate):
{related_drafts}

Generate a detailed outline for an Internet-Draft.
Return JSON: {{"title":"full draft title","abstract":"150-250 word abstract","sections":[{{"title":"section title","summary":"2-3 sentence summary of content"}}],"target_wg":"suggested IETF working group","intended_status":"informational|standards-track|experimental"}}

Include standard sections: Introduction, Terminology, Problem Statement, then 2-4 technical sections, Security Considerations, IANA Considerations.
JSON only, no fences."""

SECTION_PROMPT = """\
Write the following section of an Internet-Draft titled "{draft_title}".

Abstract: {abstract}

Full outline:
{outline_text}

Write section {section_num}: {section_title}
Summary: {section_summary}

Follow IETF Internet-Draft conventions:
- Formal, precise technical language
- Use RFC 2119 keywords (MUST, SHOULD, MAY) where appropriate
- Reference existing RFCs and drafts where relevant
- 3-6 paragraphs per section

Write the section content only (no section number or title). Plain text."""


class DraftGenerator:
    def __init__(self, config: Config, db: Database, analyzer):
        self.config = config
        self.db = db
        self.analyzer = analyzer

    def generate_outline(self, gap_topic: str) -> dict:
        """Generate draft outline from a gap topic."""
        # Find related gaps in DB
        gap_context = ""
        gaps = self.db.all_gaps()
        for g in gaps:
            if gap_topic.lower() in g["topic"].lower() or gap_topic.lower() in g["description"].lower():
                gap_context = f"Description: {g['description']}\nEvidence: {g['evidence']}"
                break

        # Get a sample of related drafts for context
        pairs = self.db.drafts_with_ratings(limit=500)
        related = []
        for draft, rating in pairs:
            if any(gap_topic.lower() in cat.lower() for cat in rating.categories):
                related.append(f"- {draft.name}: {rating.summary[:80]}")
            if len(related) >= 8:
                break

        if not related:
            # Fallback: use top-rated drafts
            for draft, rating in pairs[:5]:
                related.append(f"- {draft.name}: {rating.summary[:80]}")

        prompt = OUTLINE_PROMPT.format(
            gap_topic=gap_topic,
            gap_context=gap_context or "(No detailed gap analysis available)",
            related_drafts="\n".join(related),
        )

        text, _, _ = self.analyzer._call_claude(prompt, max_tokens=2048)
        text = self.analyzer._extract_json(text)
        return json.loads(text)

    def generate_section(self, outline: dict, section_idx: int) -> str:
        """Generate a single section of the draft."""
        sections = outline["sections"]
        section = sections[section_idx]

        outline_text = "\n".join(
            f"{i+1}. {s['title']}: {s['summary']}"
            for i, s in enumerate(sections)
        )

        prompt = SECTION_PROMPT.format(
            draft_title=outline["title"],
            abstract=outline["abstract"],
            outline_text=outline_text,
            section_num=section_idx + 1,
            section_title=section["title"],
            section_summary=section["summary"],
        )

        text, _, _ = self.analyzer._call_claude(prompt, max_tokens=2048)
        return text

    def _wrap_text(self, text: str, indent: int = 3, width: int = 69) -> str:
        """Wrap text to Internet-Draft conventions (72 char lines, indented)."""
        prefix = " " * indent
        paragraphs = text.strip().split("\n\n")
        wrapped = []
        for para in paragraphs:
            para = " ".join(para.split())  # Normalize whitespace
            lines = textwrap.wrap(para, width=width, initial_indent=prefix,
                                 subsequent_indent=prefix)
            wrapped.append("\n".join(lines))
        return "\n\n".join(wrapped)

    def assemble_draft(self, outline: dict, sections: list[str]) -> str:
        """Assemble sections into Internet-Draft text format."""
        now = datetime.now(timezone.utc)
        expires = now + timedelta(days=185)
        date_str = now.strftime("%B %Y")
        exp_str = expires.strftime("%B %d, %Y")

        title = outline["title"]
        abstract = outline["abstract"]
        status = outline.get("intended_status", "Informational")
        wg = outline.get("target_wg", "individual")

        # Generate a draft name from the title
        words = title.lower().split()
        slug = "-".join(w for w in words[:4] if w.isalnum())
        draft_name = f"draft-ai-{slug}-00"

        lines = []

        # Header
        lines.append(f"Internet-Draft                                           AI/Agent WG")
        lines.append(f"Intended status: {status:<44s}{date_str}")
        lines.append(f"Expires: {exp_str}")
        lines.append("")
        lines.append("")

        # Title (centered)
        title_line = title
        lines.append(f"         {title_line}")
        lines.append(f"         {draft_name}")
        lines.append("")

        # Abstract
        lines.append("Abstract")
        lines.append("")
        lines.append(self._wrap_text(abstract))
        lines.append("")

        # Status of This Memo
        lines.append("Status of This Memo")
        lines.append("")
        lines.append(self._wrap_text(
            "This Internet-Draft is submitted in full conformance with the "
            "provisions of BCP 78 and BCP 79."
        ))
        lines.append("")
        lines.append(self._wrap_text(
            f"This document is intended to have {status} status. "
            "Distribution of this memo is unlimited."
        ))
        lines.append("")

        # Table of Contents
        lines.append("Table of Contents")
        lines.append("")
        for i, section in enumerate(outline["sections"], 1):
            dots = "." * (60 - len(section["title"]))
            lines.append(f"   {i}.  {section['title']}  {dots}  {i + 2}")
        lines.append("")

        # Sections
        for i, (section_info, section_text) in enumerate(
            zip(outline["sections"], sections), 1
        ):
            lines.append(f"{i}.  {section_info['title']}")
            lines.append("")
            lines.append(self._wrap_text(section_text))
            lines.append("")

        # Author's Address
        lines.append("Author's Address")
        lines.append("")
        lines.append("   Generated by IETF Draft Analyzer")
        lines.append(f"   {now.strftime('%Y-%m-%d')}")
        lines.append("")

        return "\n".join(lines)

    def generate(self, gap_topic: str, output_path: str | None = None) -> str:
        """Full pipeline: outline -> sections -> assemble -> write file."""
        console.print("[bold]Step 1/3:[/] Generating outline...")
        outline = self.generate_outline(gap_topic)
        console.print(f"  Title: [cyan]{outline['title']}[/]")
        console.print(f"  Sections: {len(outline['sections'])}")
        console.print(f"  Target WG: {outline.get('target_wg', '?')}")

        console.print("\n[bold]Step 2/3:[/] Generating sections...")
        sections = []
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            BarColumn(),
            MofNCompleteColumn(),
            console=console,
        ) as progress:
            task = progress.add_task("Writing...", total=len(outline["sections"]))
            for i, s in enumerate(outline["sections"]):
                progress.update(task, description=f"Section: {s['title'][:30]}")
                text = self.generate_section(outline, i)
                sections.append(text)
                progress.advance(task)

        console.print("\n[bold]Step 3/3:[/] Assembling draft...")
        draft_text = self.assemble_draft(outline, sections)

        out = Path(output_path) if output_path else Path(self.config.data_dir) / "reports" / "generated-draft.txt"
        out.parent.mkdir(parents=True, exist_ok=True)
        out.write_text(draft_text)
        return str(out)
