#!/usr/bin/env python3
"""
Capture output utility for Mainline.

This script captures the output of a Mainline pipeline using NullDisplay
and saves it to a JSON file for comparison with other branches.
"""

import argparse
import json
import time
from pathlib import Path

from engine.display import DisplayRegistry
from engine.pipeline import Pipeline, PipelineConfig, PipelineContext
from engine.pipeline.adapters import create_stage_from_display
from engine.pipeline.presets import get_preset


def capture_pipeline_output(
    preset_name: str,
    output_file: str,
    frames: int = 60,
    width: int = 80,
    height: int = 24,
):
    """Capture pipeline output for a given preset.

    Args:
        preset_name: Name of preset to use
        output_file: Path to save captured output
        frames: Number of frames to capture
        width: Terminal width
        height: Terminal height
    """
    print(f"Capturing output for preset '{preset_name}'...")

    # Get preset
    preset = get_preset(preset_name)
    if not preset:
        print(f"Error: Preset '{preset_name}' not found")
        return False

    # Create NullDisplay with recording
    display = DisplayRegistry.create("null")
    display.init(width, height)
    display.start_recording()

    # Build pipeline
    config = PipelineConfig(
        source=preset.source,
        display="null",  # Use null display
        camera=preset.camera,
        effects=preset.effects,
        enable_metrics=False,
    )

    # Create pipeline context with params
    from engine.pipeline.params import PipelineParams

    params = PipelineParams(
        source=preset.source,
        display="null",
        camera_mode=preset.camera,
        effect_order=preset.effects,
        viewport_width=preset.viewport_width,
        viewport_height=preset.viewport_height,
        camera_speed=preset.camera_speed,
    )

    ctx = PipelineContext()
    ctx.params = params

    pipeline = Pipeline(config=config, context=ctx)

    # Add stages based on preset
    from engine.data_sources.sources import HeadlinesDataSource
    from engine.pipeline.adapters import DataSourceStage

    # Add source stage
    source = HeadlinesDataSource()
    pipeline.add_stage("source", DataSourceStage(source, name="headlines"))

    # Add message overlay if enabled
    if getattr(preset, "enable_message_overlay", False):
        from engine import config as engine_config
        from engine.pipeline.adapters import MessageOverlayConfig, MessageOverlayStage

        overlay_config = MessageOverlayConfig(
            enabled=True,
            display_secs=getattr(engine_config, "MESSAGE_DISPLAY_SECS", 30),
            topic_url=getattr(engine_config, "NTFY_TOPIC", None),
        )
        pipeline.add_stage(
            "message_overlay", MessageOverlayStage(config=overlay_config)
        )

    # Add display stage
    pipeline.add_stage("display", create_stage_from_display(display, "null"))

    # Build and initialize
    pipeline.build()
    if not pipeline.initialize():
        print("Error: Failed to initialize pipeline")
        return False

    # Capture frames
    print(f"Capturing {frames} frames...")
    start_time = time.time()

    for frame in range(frames):
        try:
            pipeline.execute([])
            if frame % 10 == 0:
                print(f"  Frame {frame}/{frames}")
        except Exception as e:
            print(f"Error on frame {frame}: {e}")
            break

    elapsed = time.time() - start_time
    print(f"Captured {frame + 1} frames in {elapsed:.2f}s")

    # Get captured frames
    captured_frames = display.get_frames()
    print(f"Retrieved {len(captured_frames)} frames from display")

    # Save to JSON
    output_path = Path(output_file)
    output_path.parent.mkdir(parents=True, exist_ok=True)

    recording_data = {
        "version": 1,
        "preset": preset_name,
        "display": "null",
        "width": width,
        "height": height,
        "frame_count": len(captured_frames),
        "frames": [
            {
                "frame_number": i,
                "buffer": frame,
                "width": width,
                "height": height,
            }
            for i, frame in enumerate(captured_frames)
        ],
    }

    with open(output_path, "w") as f:
        json.dump(recording_data, f, indent=2)

    print(f"Saved recording to {output_path}")
    return True


def main():
    parser = argparse.ArgumentParser(description="Capture Mainline pipeline output")
    parser.add_argument(
        "--preset",
        default="demo",
        help="Preset name to use (default: demo)",
    )
    parser.add_argument(
        "--output",
        default="output/capture.json",
        help="Output file path (default: output/capture.json)",
    )
    parser.add_argument(
        "--frames",
        type=int,
        default=60,
        help="Number of frames to capture (default: 60)",
    )
    parser.add_argument(
        "--width",
        type=int,
        default=80,
        help="Terminal width (default: 80)",
    )
    parser.add_argument(
        "--height",
        type=int,
        default=24,
        help="Terminal height (default: 24)",
    )

    args = parser.parse_args()

    success = capture_pipeline_output(
        preset_name=args.preset,
        output_file=args.output,
        frames=args.frames,
        width=args.width,
        height=args.height,
    )

    return 0 if success else 1


if __name__ == "__main__":
    exit(main())
