"""
Animation Report Display Backend

Captures frames from pipeline stages and generates an interactive HTML report
showing before/after states for each transformative stage.
"""

import time
from dataclasses import dataclass, field
from datetime import datetime
from pathlib import Path
from typing import Any

from sideline.display.streaming import compute_diff


@dataclass
class CapturedFrame:
    """A captured frame with metadata."""

    stage: str
    buffer: list[str]
    timestamp: float
    frame_number: int
    diff_from_previous: dict[str, Any] | None = None


@dataclass
class StageCapture:
    """Captures frames for a single pipeline stage."""

    name: str
    frames: list[CapturedFrame] = field(default_factory=list)
    start_time: float = field(default_factory=time.time)
    end_time: float = 0.0

    def add_frame(
        self,
        buffer: list[str],
        frame_number: int,
        previous_buffer: list[str] | None = None,
    ) -> None:
        """Add a captured frame."""
        timestamp = time.time()
        diff = None
        if previous_buffer is not None:
            diff_data = compute_diff(previous_buffer, buffer)
            diff = {
                "changed_lines": len(diff_data.changed_lines),
                "total_lines": len(buffer),
                "width": diff_data.width,
                "height": diff_data.height,
            }

        frame = CapturedFrame(
            stage=self.name,
            buffer=list(buffer),
            timestamp=timestamp,
            frame_number=frame_number,
            diff_from_previous=diff,
        )
        self.frames.append(frame)

    def finish(self) -> None:
        """Mark capture as finished."""
        self.end_time = time.time()


class AnimationReportDisplay:
    """
    Display backend that captures frames for animation report generation.

    Instead of rendering to terminal, this display captures the buffer at each
    stage and stores it for later HTML report generation.
    """

    width: int = 80
    height: int = 24

    def __init__(self, output_dir: str = "./reports"):
        """
        Initialize the animation report display.

        Args:
            output_dir: Directory where reports will be saved
        """
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)

        self._stages: dict[str, StageCapture] = {}
        self._current_stage: str = ""
        self._previous_buffer: list[str] | None = None
        self._frame_number: int = 0
        self._total_frames: int = 0
        self._start_time: float = 0.0

    def init(self, width: int, height: int, reuse: bool = False) -> None:
        """Initialize display with dimensions."""
        self.width = width
        self.height = height
        self._start_time = time.time()

    def show(self, buffer: list[str], border: bool = False) -> None:
        """
        Capture a frame for the current stage.

        Args:
            buffer: The frame buffer to capture
            border: Border flag (ignored)
        """
        if not self._current_stage:
            # If no stage is set, use a default name
            self._current_stage = "final"

        if self._current_stage not in self._stages:
            self._stages[self._current_stage] = StageCapture(self._current_stage)

        stage = self._stages[self._current_stage]
        stage.add_frame(buffer, self._frame_number, self._previous_buffer)

        self._previous_buffer = list(buffer)
        self._frame_number += 1
        self._total_frames += 1

    def start_stage(self, stage_name: str) -> None:
        """
        Start capturing frames for a new stage.

        Args:
            stage_name: Name of the stage (e.g., "noise", "fade", "firehose")
        """
        if self._current_stage and self._current_stage in self._stages:
            # Finish previous stage
            self._stages[self._current_stage].finish()

        self._current_stage = stage_name
        self._previous_buffer = None  # Reset for new stage

    def clear(self) -> None:
        """Clear the display (no-op for report display)."""
        pass

    def cleanup(self) -> None:
        """Cleanup resources."""
        # Finish current stage
        if self._current_stage and self._current_stage in self._stages:
            self._stages[self._current_stage].finish()

    def get_dimensions(self) -> tuple[int, int]:
        """Get current dimensions."""
        return (self.width, self.height)

    def get_stages(self) -> dict[str, StageCapture]:
        """Get all captured stages."""
        return self._stages

    def generate_report(self, title: str = "Animation Report") -> Path:
        """
        Generate an HTML report with captured frames and animations.

        Args:
            title: Title of the report

        Returns:
            Path to the generated HTML file
        """
        report_path = self.output_dir / f"animation_report_{int(time.time())}.html"
        html_content = self._build_html(title)
        report_path.write_text(html_content)
        return report_path

    def _build_html(self, title: str) -> str:
        """Build the HTML content for the report."""
        # Collect all frames across stages
        all_frames = []
        for stage_name, stage in self._stages.items():
            for frame in stage.frames:
                all_frames.append(frame)

        # Sort frames by timestamp
        all_frames.sort(key=lambda f: f.timestamp)

        # Build stage sections
        stages_html = ""
        for stage_name, stage in self._stages.items():
            stages_html += self._build_stage_section(stage_name, stage)

        # Build full HTML
        html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{title}</title>
    <style>
        * {{
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }}
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: #1a1a2e;
            color: #eee;
            padding: 20px;
            line-height: 1.6;
        }}
        .container {{
            max-width: 1400px;
            margin: 0 auto;
        }}
        .header {{
            background: linear-gradient(135deg, #16213e 0%, #1a1a2e 100%);
            padding: 30px;
            border-radius: 12px;
            margin-bottom: 30px;
            text-align: center;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
        }}
        .header h1 {{
            font-size: 2.5em;
            margin-bottom: 10px;
            background: linear-gradient(90deg, #00d4ff, #00ff88);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }}
        .header .meta {{
            color: #888;
            font-size: 0.9em;
        }}
        .stats-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 15px;
            margin: 20px 0;
        }}
        .stat-card {{
            background: #16213e;
            padding: 15px;
            border-radius: 8px;
            text-align: center;
        }}
        .stat-value {{
            font-size: 1.8em;
            font-weight: bold;
            color: #00ff88;
        }}
        .stat-label {{
            color: #888;
            font-size: 0.85em;
            margin-top: 5px;
        }}
        .stage-section {{
            background: #16213e;
            border-radius: 12px;
            margin-bottom: 25px;
            overflow: hidden;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        }}
        .stage-header {{
            background: #1f2a48;
            padding: 15px 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: pointer;
            user-select: none;
        }}
        .stage-header:hover {{
            background: #253252;
        }}
        .stage-name {{
            font-weight: bold;
            font-size: 1.1em;
            color: #00d4ff;
        }}
        .stage-info {{
            color: #888;
            font-size: 0.9em;
        }}
        .stage-content {{
            padding: 20px;
        }}
        .frames-container {{
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 15px;
        }}
        .frame-card {{
            background: #0f0f1a;
            border-radius: 8px;
            overflow: hidden;
            border: 1px solid #333;
            transition: transform 0.2s, box-shadow 0.2s;
        }}
        .frame-card:hover {{
            transform: translateY(-2px);
            box-shadow: 0 4px 15px rgba(0,212,255,0.2);
        }}
        .frame-header {{
            background: #1a1a2e;
            padding: 10px 15px;
            font-size: 0.85em;
            color: #888;
            border-bottom: 1px solid #333;
            display: flex;
            justify-content: space-between;
        }}
        .frame-number {{
            color: #00ff88;
        }}
        .frame-diff {{
            color: #ff6b6b;
        }}
        .frame-content {{
            padding: 10px;
            font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
            font-size: 11px;
            line-height: 1.3;
            white-space: pre;
            overflow-x: auto;
            max-height: 200px;
            overflow-y: auto;
        }}
        .timeline-section {{
            background: #16213e;
            border-radius: 12px;
            padding: 20px;
            margin-bottom: 25px;
        }}
        .timeline-header {{
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }}
        .timeline-title {{
            font-weight: bold;
            color: #00d4ff;
        }}
        .timeline-controls {{
            display: flex;
            gap: 10px;
        }}
        .timeline-controls button {{
            background: #1f2a48;
            border: 1px solid #333;
            color: #eee;
            padding: 8px 15px;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s;
        }}
        .timeline-controls button:hover {{
            background: #253252;
            border-color: #00d4ff;
        }}
        .timeline-controls button.active {{
            background: #00d4ff;
            color: #000;
        }}
        .timeline-canvas {{
            width: 100%;
            height: 100px;
            background: #0f0f1a;
            border-radius: 8px;
            position: relative;
            overflow: hidden;
        }}
        .timeline-track {{
            position: absolute;
            top: 50%;
            left: 0;
            right: 0;
            height: 4px;
            background: #333;
            transform: translateY(-50%);
        }}
        .timeline-marker {{
            position: absolute;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 12px;
            height: 12px;
            background: #00d4ff;
            border-radius: 50%;
            cursor: pointer;
            transition: all 0.2s;
        }}
        .timeline-marker:hover {{
            transform: translate(-50%, -50%) scale(1.3);
            box-shadow: 0 0 10px #00d4ff;
        }}
        .timeline-marker.stage-{{stage_name}} {{
            background: var(--stage-color, #00d4ff);
        }}
        .comparison-view {{
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            margin-top: 20px;
        }}
        .comparison-panel {{
            background: #0f0f1a;
            border-radius: 8px;
            padding: 15px;
            border: 1px solid #333;
        }}
        .comparison-panel h4 {{
            color: #888;
            margin-bottom: 10px;
            font-size: 0.9em;
        }}
        .comparison-content {{
            font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
            font-size: 11px;
            line-height: 1.3;
            white-space: pre;
        }}
        .diff-added {{
            background: rgba(0, 255, 136, 0.2);
        }}
        .diff-removed {{
            background: rgba(255, 107, 107, 0.2);
        }}
        @keyframes pulse {{
            0%, 100% {{ opacity: 1; }}
            50% {{ opacity: 0.7; }}
        }}
        .animating {{
            animation: pulse 1s infinite;
        }}
        .footer {{
            text-align: center;
            color: #666;
            padding: 20px;
            font-size: 0.9em;
        }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🎬 {title}</h1>
            <div class="meta">
                Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} |
                Total Frames: {self._total_frames} |
                Duration: {time.time() - self._start_time:.2f}s
            </div>
            <div class="stats-grid">
                <div class="stat-card">
                    <div class="stat-value">{len(self._stages)}</div>
                    <div class="stat-label">Pipeline Stages</div>
                </div>
                <div class="stat-card">
                    <div class="stat-value">{self._total_frames}</div>
                    <div class="stat-label">Total Frames</div>
                </div>
                <div class="stat-card">
                    <div class="stat-value">{time.time() - self._start_time:.2f}s</div>
                    <div class="stat-label">Capture Duration</div>
                </div>
                <div class="stat-card">
                    <div class="stat-value">{self.width}x{self.height}</div>
                    <div class="stat-label">Resolution</div>
                </div>
            </div>
        </div>

        <div class="timeline-section">
            <div class="timeline-header">
                <div class="timeline-title">Timeline</div>
                <div class="timeline-controls">
                    <button onclick="playAnimation()">▶ Play</button>
                    <button onclick="pauseAnimation()">⏸ Pause</button>
                    <button onclick="stepForward()">⏭ Step</button>
                </div>
            </div>
            <div class="timeline-canvas" id="timeline">
                <div class="timeline-track"></div>
                <!-- Timeline markers will be added by JavaScript -->
            </div>
        </div>

        {stages_html}

        <div class="footer">
            <p>Animation Report generated by Mainline</p>
            <p>Use the timeline controls above to play/pause the animation</p>
        </div>
    </div>

    <script>
        // Animation state
        let currentFrame = 0;
        let isPlaying = false;
        let animationInterval = null;
        const totalFrames = {len(all_frames)};

        // Stage colors for timeline markers
        const stageColors = {{
            {self._build_stage_colors()}
        }};

        // Initialize timeline
        function initTimeline() {{
            const timeline = document.getElementById('timeline');
            const track = timeline.querySelector('.timeline-track');

            {self._build_timeline_markers(all_frames)}
        }}

        function playAnimation() {{
            if (isPlaying) return;
            isPlaying = true;
            animationInterval = setInterval(() => {{
                currentFrame = (currentFrame + 1) % totalFrames;
                updateFrameDisplay();
            }}, 100);
        }}

        function pauseAnimation() {{
            isPlaying = false;
            if (animationInterval) {{
                clearInterval(animationInterval);
                animationInterval = null;
            }}
        }}

        function stepForward() {{
            currentFrame = (currentFrame + 1) % totalFrames;
            updateFrameDisplay();
        }}

        function updateFrameDisplay() {{
            // Highlight current frame in timeline
            const markers = document.querySelectorAll('.timeline-marker');
            markers.forEach((marker, index) => {{
                if (index === currentFrame) {{
                    marker.style.transform = 'translate(-50%, -50%) scale(1.5)';
                    marker.style.boxShadow = '0 0 15px #00ff88';
                }} else {{
                    marker.style.transform = 'translate(-50%, -50%) scale(1)';
                    marker.style.boxShadow = 'none';
                }}
            }});
        }}

        // Initialize on page load
        document.addEventListener('DOMContentLoaded', initTimeline);
    </script>
</body>
</html>
"""
        return html

    def _build_stage_section(self, stage_name: str, stage: StageCapture) -> str:
        """Build HTML for a single stage section."""
        frames_html = ""
        for i, frame in enumerate(stage.frames):
            diff_info = ""
            if frame.diff_from_previous:
                changed = frame.diff_from_previous.get("changed_lines", 0)
                total = frame.diff_from_previous.get("total_lines", 0)
                diff_info = f'<span class="frame-diff">Δ {changed}/{total}</span>'

            frames_html += f"""
            <div class="frame-card">
                <div class="frame-header">
                    <span>Frame <span class="frame-number">{frame.frame_number}</span></span>
                    {diff_info}
                </div>
                <div class="frame-content">{self._escape_html("".join(frame.buffer))}</div>
            </div>
            """

        return f"""
        <div class="stage-section">
            <div class="stage-header" onclick="this.nextElementSibling.classList.toggle('hidden')">
                <span class="stage-name">{stage_name}</span>
                <span class="stage-info">{len(stage.frames)} frames</span>
            </div>
            <div class="stage-content">
                <div class="frames-container">
                    {frames_html}
                </div>
            </div>
        </div>
        """

    def _build_timeline(self, all_frames: list[CapturedFrame]) -> str:
        """Build timeline HTML."""
        if not all_frames:
            return ""

        markers_html = ""
        for i, frame in enumerate(all_frames):
            left_percent = (i / len(all_frames)) * 100
            markers_html += f'<div class="timeline-marker" style="left: {left_percent}%" data-frame="{i}"></div>'

        return markers_html

    def _build_stage_colors(self) -> str:
        """Build stage color mapping for JavaScript."""
        colors = [
            "#00d4ff",
            "#00ff88",
            "#ff6b6b",
            "#ffd93d",
            "#a855f7",
            "#ec4899",
            "#14b8a6",
            "#f97316",
            "#8b5cf6",
            "#06b6d4",
        ]
        color_map = ""
        for i, stage_name in enumerate(self._stages.keys()):
            color = colors[i % len(colors)]
            color_map += f'            "{stage_name}": "{color}",\n'
        return color_map.rstrip(",\n")

    def _build_timeline_markers(self, all_frames: list[CapturedFrame]) -> str:
        """Build timeline markers in JavaScript."""
        if not all_frames:
            return ""

        markers_js = ""
        for i, frame in enumerate(all_frames):
            left_percent = (i / len(all_frames)) * 100
            stage_color = f"stageColors['{frame.stage}']"
            markers_js += f"""
            const marker{i} = document.createElement('div');
            marker{i}.className = 'timeline-marker stage-{{frame.stage}}';
            marker{i}.style.left = '{left_percent}%';
            marker{i}.style.setProperty('--stage-color', {stage_color});
            marker{i}.onclick = () => {{
                currentFrame = {i};
                updateFrameDisplay();
            }};
            timeline.appendChild(marker{i});
            """

        return markers_js

    def _escape_html(self, text: str) -> str:
        """Escape HTML special characters."""
        return (
            text.replace("&", "&amp;")
            .replace("<", "&lt;")
            .replace(">", "&gt;")
            .replace('"', "&quot;")
            .replace("'", "&#39;")
        )
