"""Automated writing pipeline for drafting and finalizing chapters."""

import asyncio
import multiprocessing
import sys
from collections import deque
from pathlib import Path

import click
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn

console = Console()


def _run_server(project_root: Path, port: int):
    """Run the web server in a subprocess with suppressed output."""
    import logging
    import os

    from agent_xs.web import create_app

    # Suppress all output from the server
    sys.stdout = open(os.devnull, "w")
    sys.stderr = open(os.devnull, "w")

    # Disable Flask/Werkzeug logging
    logging.getLogger("werkzeug").setLevel(logging.ERROR)
    logging.getLogger("flask").setLevel(logging.ERROR)

    app = create_app(project_root)
    app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False)


@click.command("auto")
@click.option(
    "-n",
    "--iterations",
    default=100,
    type=int,
    help="Number of iterations to run (default: 100)",
)
@click.option(
    "--path",
    type=click.Path(exists=True, file_okay=False, path_type=Path),
    default=".",
    help="Project directory (default: current directory)",
)
@click.option(
    "--serve",
    "-s",
    is_flag=True,
    help="Start a web server in the background to view content",
)
@click.option(
    "--port",
    "-p",
    default=8000,
    type=int,
    help="Port for the web server (default: 8000, only used with --serve)",
)
def auto_write(iterations: int, path: Path, serve: bool, port: int):
    """Run the automated writing pipeline.

    Automatically alternates between drafting and finalizing chapters,
    keeping drafts 3-4 chapters ahead of finals.

    Requires Claude Agent SDK to be installed and configured.
    """
    from agent_xs.core.pipeline import NovelPipeline

    project_root = path.resolve()
    pipeline = NovelPipeline(project_root)

    console.print(Panel.fit(
        "[bold]Novel Auto-Writing Pipeline[/]",
        border_style="blue",
    ))

    # Start web server in background if requested
    server_process = None
    if serve:
        console.print(f"\n[bold]Starting web server on port {port}...[/]")
        server_process = multiprocessing.Process(
            target=_run_server,
            args=(project_root, port),
            daemon=True,
        )
        server_process.start()
        console.print(f"  URL: [cyan]http://localhost:{port}[/]")

    # Check prerequisites
    console.print("\n[bold]Checking prerequisites...[/]")
    is_complete, message = pipeline.check_prerequisites()

    if not is_complete:
        console.print(f"\n[red]{message}[/]")
        console.print("\nPlease complete the prerequisite stages first.")
        if server_process and server_process.is_alive():
            server_process.terminate()
        sys.exit(1)

    console.print(f"[green]{message}[/]")

    # Show current progress
    draft_count, final_count = pipeline.count_chapters()
    console.print(f"\n[bold]Current progress:[/]")
    console.print(f"  Drafts: {draft_count} chapters")
    console.print(f"  Finals: {final_count} chapters")

    # Run the pipeline
    console.print(f"\n[bold]Starting pipeline ({iterations} iterations)...[/]\n")

    try:
        asyncio.run(_run_pipeline(pipeline, iterations))
    except KeyboardInterrupt:
        console.print("\n\n[yellow]Interrupted by user.[/]")
        if server_process and server_process.is_alive():
            console.print("[dim]Stopping web server...[/]")
            server_process.terminate()
        sys.exit(1)
    except ImportError as e:
        console.print(f"\n[red]Error:[/] {e}")
        console.print("\nMake sure claude-agent-sdk is installed:")
        console.print("  [cyan]pip install claude-agent-sdk[/]")
        if server_process and server_process.is_alive():
            server_process.terminate()
        sys.exit(1)
    except Exception as e:
        console.print(f"\n[red]Error:[/] {e}")
        import traceback
        traceback.print_exc()
        if server_process and server_process.is_alive():
            server_process.terminate()
        sys.exit(1)
    finally:
        # Clean up server process on normal exit
        if server_process and server_process.is_alive():
            console.print("[dim]Stopping web server...[/]")
            server_process.terminate()


async def _run_pipeline(pipeline, num_iterations: int):
    """Run the writing pipeline."""
    try:
        from claude_agent_sdk import (
            ClaudeSDKClient,
            ClaudeAgentOptions,
            AssistantMessage,
        )
    except ImportError:
        raise ImportError(
            "claude-agent-sdk is required for auto-write. "
            "Install it with: pip install claude-agent-sdk"
        )

    options = ClaudeAgentOptions(
        cwd=str(pipeline.cwd),
        permission_mode="bypassPermissions",
        allowed_tools=[
            "Read",
            "Write",
            "Edit",
            "Glob",
            "Grep",
            "Bash",
            "Skill",
        ],
        setting_sources=["project"],
    )

    for iteration in range(1, num_iterations + 1):
        async with ClaudeSDKClient(options=options) as client:
            action, chapter_num = pipeline.get_next_action()
            action_name = "编写草稿" if action == "draft" else "定稿"
            command = "/draft" if action == "draft" else "/finalize"

            prompt = f"{command} {chapter_num} 不需要向我提问，按照你的想法直接写，我相信你的判断。"

            console.print(f"[bold cyan]Iteration {iteration}/{num_iterations}[/]")
            console.print(f"  Action: {action_name} Chapter {chapter_num}")

            await client.query(prompt)

            # Keep last 3 text messages for display
            text_history = deque(maxlen=3)
            text_history.append(f"{action_name}中...")
            # Tool activities for current text message (cleared on new text)
            # Each item: {"name": str, "args": str}
            tool_activities = []

            def format_args(input_data):
                """Format tool input as brief string."""
                if not input_data:
                    return ""
                if isinstance(input_data, dict):
                    # Show first key-value or file_path if present
                    if "file_path" in input_data:
                        return str(input_data["file_path"])[:40]
                    if "path" in input_data:
                        return str(input_data["path"])[:40]
                    if "pattern" in input_data:
                        return str(input_data["pattern"])[:40]
                    if "command" in input_data:
                        return str(input_data["command"])[:40]
                    # Otherwise show first value
                    for v in input_data.values():
                        return str(v)[:40]
                return str(input_data)[:40]

            with Progress(
                SpinnerColumn(finished_text=" "),
                TextColumn("{task.description}"),
                console=console,
            ) as progress:
                # Create tasks: 2 history + 1 current + up to 5 tool lines
                history1 = progress.add_task("", total=1, completed=1, visible=False)
                history2 = progress.add_task("", total=1, completed=1, visible=False)
                current = progress.add_task(f"{action_name}中...", total=None)
                # Tool activity lines (all finished/dim)
                tool_tasks = [
                    progress.add_task("", total=1, completed=1, visible=False)
                    for _ in range(5)
                ]

                def update_display():
                    messages = list(text_history)
                    # Update history lines (dim, truncated, with checkmark in description)
                    if len(messages) >= 3:
                        text1 = messages[-3][:60] + "..." if len(messages[-3]) > 60 else messages[-3]
                        text1 = text1.replace("\n", " ")
                        progress.update(history1, description=f"[dim]✓ {text1}[/]", visible=True)
                    else:
                        progress.update(history1, visible=False)

                    if len(messages) >= 2:
                        text2 = messages[-2][:60] + "..." if len(messages[-2]) > 60 else messages[-2]
                        text2 = text2.replace("\n", " ")
                        progress.update(history2, description=f"[dim]✓ {text2}[/]", visible=True)
                    else:
                        progress.update(history2, visible=False)

                    # Update current line (normal color with spinner)
                    if messages:
                        text = messages[-1][:80] + "..." if len(messages[-1]) > 80 else messages[-1]
                        progress.update(current, description=text)

                    # Update tool activity lines (dim, with ◦ icon)
                    # Show last 5 tool activities
                    recent_tools = tool_activities[-5:] if tool_activities else []
                    for i, task_id in enumerate(tool_tasks):
                        if i < len(recent_tools):
                            tool = recent_tools[i]
                            # Format: ◦ ToolName(args)
                            tool_text = f"{tool['name']}"
                            if tool["args"]:
                                tool_text += f"({tool['args']})"
                            tool_text = tool_text[:65] + "..." if len(tool_text) > 65 else tool_text
                            progress.update(task_id, description=f"[dim]  ◦ {tool_text}[/]", visible=True)
                        else:
                            progress.update(task_id, visible=False)

                async for message in client.receive_response():
                    if isinstance(message, AssistantMessage):
                        for block in message.content:
                            if hasattr(block, "text") and block.text:
                                # New text message - clear tool activities
                                tool_activities.clear()
                                text_history.append(block.text)
                                update_display()
                            elif hasattr(block, "name") and hasattr(block, "id"):
                                # ToolUseBlock: has name, input, id
                                tool_name = block.name
                                tool_input = getattr(block, "input", None)
                                tool_activities.append({
                                    "name": tool_name,
                                    "args": format_args(tool_input),
                                })
                                update_display()

            console.print(f"  [green]Chapter {chapter_num} {action_name}完成[/]\n")

    console.print(Panel.fit(
        f"[bold green]Pipeline complete![/]\n"
        f"Ran {num_iterations} iterations.",
        border_style="green",
    ))
