"""Context compression CLI commands for Oclawma."""

from __future__ import annotations

from pathlib import Path

import click

from oclawma.config import DEFAULT_CONFIG_PATH, Config
from oclawma.config.utils import load_context_budget
from oclawma.context import ContextBudget, ContextCompressionSuggestions
from oclawma.context.compression import TokenBreakdown
from oclawma.session import ConversationHistory


@click.group(name="compact")
def compact_cli() -> None:
    """Context compression commands.

    Analyze and compress context to stay within token budget limits.

    Examples:
        oclawma compact              # Show compression suggestions
        oclawma compact analyze      # Same as above
        oclawma compact execute      # Execute compression plan
        oclawma compact breakdown    # Show detailed token breakdown
    """
    pass


@compact_cli.command(name="analyze")
@click.option(
    "--budget",
    type=int,
    default=8192,
    help="Token budget (default: 8192)",
)
@click.option(
    "--usage",
    type=int,
    default=None,
    help="Current token usage (if not provided, estimates from history)",
)
@click.option(
    "--config-path",
    type=click.Path(exists=False),
    help="Path to config file",
)
@click.pass_context
def analyze_cmd(
    ctx: click.Context,
    budget: int,
    usage: int | None,
    config_path: str | None,
) -> None:
    """Analyze current context and show compression suggestions."""
    cfg_path = click.Path(path_type=Path).convert(config_path or str(DEFAULT_CONFIG_PATH), None, ctx) if config_path else DEFAULT_CONFIG_PATH  # type: ignore

    # Load config for budget settings
    try:
        if cfg_path.exists():
            config = Config.load(cfg_path)
            context_budget = load_context_budget(config)
        else:
            context_budget = ContextBudget(total_budget=budget)
    except Exception:
        context_budget = ContextBudget(total_budget=budget)

    # Override with explicit usage if provided
    if usage is not None:
        context_budget.reset()
        context_budget.allocate(usage, strict=False)

    # Create suggestion analyzer
    suggester = ContextCompressionSuggestions(budget=context_budget)

    # Create a mock history for demonstration (in real use, this would come from session)
    history = ConversationHistory()

    # Generate plan
    plan = suggester.analyze(history=history)

    # Format and display
    click.echo(suggester.format_suggestions(plan, verbose=True))


@compact_cli.command(name="breakdown")
@click.option(
    "--config-path",
    type=click.Path(exists=False),
    help="Path to config file",
)
@click.option(
    "--system",
    type=int,
    default=500,
    help="System prompt tokens",
)
@click.option(
    "--conversation",
    type=int,
    default=2000,
    help="Conversation history tokens",
)
@click.option(
    "--files",
    type=int,
    default=1000,
    help="File contents tokens",
)
@click.option(
    "--tools",
    type=int,
    default=500,
    help="Tool results tokens",
)
@click.option(
    "--attachments",
    type=int,
    default=0,
    help="Attachments tokens",
)
@click.pass_context
def breakdown_cmd(
    ctx: click.Context,
    config_path: str | None,
    system: int,
    conversation: int,
    files: int,
    tools: int,
    attachments: int,
) -> None:
    """Show detailed token usage breakdown."""
    cfg_path = click.Path(path_type=Path).convert(config_path or str(DEFAULT_CONFIG_PATH), None, ctx) if config_path else DEFAULT_CONFIG_PATH  # type: ignore

    # Load config for budget settings
    try:
        if cfg_path.exists():
            config = Config.load(cfg_path)
            budget = load_context_budget(config)
        else:
            budget = ContextBudget()
    except Exception:
        budget = ContextBudget()

    # Create breakdown
    breakdown = TokenBreakdown(
        system_prompt=system,
        conversation_history=conversation,
        file_contents=files,
        tool_results=tools,
        attachments=attachments,
    )

    click.echo("╔══════════════════════════════════════════════════════════╗")
    click.echo("║           TOKEN USAGE BREAKDOWN                          ║")
    click.echo("╚══════════════════════════════════════════════════════════╝")
    click.echo()
    click.echo(breakdown.visualize(budget.total_budget))
    click.echo()
    click.echo("─" * 50)
    click.echo(f"Budget: {budget.total_budget:,} tokens")
    click.echo(f"Used:   {breakdown.total:,} tokens")
    click.echo(f"Free:   {budget.total_budget - breakdown.total:,} tokens")

    usage_pct = (breakdown.total / budget.total_budget) * 100
    if usage_pct >= 87:
        click.echo(click.style(f"⚠️  Usage: {usage_pct:.1f}% - CRITICAL", fg="red", bold=True))
    elif usage_pct >= 75:
        click.echo(click.style(f"⚠️  Usage: {usage_pct:.1f}% - WARNING", fg="yellow"))
    else:
        click.echo(click.style(f"✓ Usage: {usage_pct:.1f}% - OK", fg="green"))


@compact_cli.command(name="execute")
@click.option(
    "--config-path",
    type=click.Path(exists=False),
    help="Path to config file",
)
@click.option(
    "--dry-run",
    is_flag=True,
    help="Show what would be done without executing",
)
@click.pass_context
def execute_cmd(
    ctx: click.Context,
    config_path: str | None,
    dry_run: bool,
) -> None:
    """Execute the compression plan.

    This command will:
    1. Analyze current context
    2. Execute auto-compressible actions
    3. Show remaining manual actions
    """
    cfg_path = click.Path(path_type=Path).convert(config_path or str(DEFAULT_CONFIG_PATH), None, ctx) if config_path else DEFAULT_CONFIG_PATH  # type: ignore

    # Load config
    try:
        if cfg_path.exists():
            config = Config.load(cfg_path)
            budget = load_context_budget(config)
        else:
            config = Config()
            budget = ContextBudget()
    except Exception as e:
        click.echo(f"⚠️  Warning: Could not load config: {e}")
        config = Config()
        budget = ContextBudget()

    click.echo("🗜️  CONTEXT COMPRESSION")
    click.echo("═" * 50)
    click.echo()

    # Create suggestion analyzer
    suggester = ContextCompressionSuggestions(budget=budget)

    # Mock history for now (in real implementation, would load from session file)
    history = ConversationHistory()

    # Generate plan
    plan = suggester.analyze(history=history)

    if not plan.suggestions:
        click.echo("✓ No compression needed. Context is within budget.")
        click.echo(
            f"Current usage: {plan.current_usage:,} / {plan.budget:,} tokens ({plan.usage_percent:.1f}%)"
        )
        return

    # Show plan
    click.echo(
        f"Current usage: {plan.current_usage:,} / {plan.budget:,} tokens ({plan.usage_percent:.1f}%)"
    )
    click.echo()
    click.echo("Actions to execute:")
    click.echo("─" * 50)

    auto_suggestions = plan.get_executable_suggestions()
    manual_suggestions = [s for s in plan.suggestions if not s.auto_executable]

    if auto_suggestions:
        for suggestion in auto_suggestions:
            click.echo(f"  ✓ {suggestion.title}: ~{suggestion.estimated_savings:,} tokens")
    else:
        click.echo("  (No auto-executable actions available)")

    if manual_suggestions:
        click.echo()
        click.echo("Manual actions (require confirmation):")
        for suggestion in manual_suggestions:
            click.echo(f"  ○ {suggestion.title}: ~{suggestion.estimated_savings:,} tokens")

    click.echo()
    click.echo(f"Estimated total savings: ~{plan.total_potential_savings:,} tokens")
    click.echo(f"Projected usage: {plan.projected_usage:,} tokens ({plan.projected_percent:.1f}%)")

    if dry_run:
        click.echo()
        click.echo(click.style("(Dry run - no changes made)", fg="yellow"))
        return

    # Execute auto-suggestions
    if auto_suggestions:
        click.echo()
        click.echo("Executing compression...")

        for suggestion in auto_suggestions:
            click.echo(f"  → {suggestion.title}...", nl=False)

            # In real implementation, these would call actual compression functions
            if suggestion.action.value == "summarize":
                # Would call summarizer
                click.echo(click.style(" ✓", fg="green"))
            elif suggestion.action.value == "compact":
                # Would run full compact
                click.echo(click.style(" ✓", fg="green"))
            elif suggestion.action.value == "clear_attachments":
                click.echo(click.style(" ✓", fg="green"))
            else:
                click.echo(click.style(" skipped", fg="yellow"))

        click.echo()
        click.echo(click.style("✓ Compression complete!", fg="green", bold=True))

        if manual_suggestions:
            click.echo()
            click.echo("Remaining manual actions:")
            for suggestion in manual_suggestions:
                click.echo(f"  • {suggestion.command} - {suggestion.title}")
    else:
        click.echo()
        click.echo("No auto-executable actions. Use individual commands to compress context.")


# Default command (when just 'oclawma compact' is run)
@compact_cli.command(name="show")
@click.option(
    "--config-path",
    type=click.Path(exists=False),
    help="Path to config file",
)
@click.pass_context
def show_cmd(ctx: click.Context, config_path: str | None) -> None:
    """Show compression suggestions (default)."""
    # Forward to analyze
    ctx.forward(analyze_cmd)
