"""Batch plot generation for comprehensive signal visualization.

Generate multiple related plots from signal traces in a single operation,
useful for comprehensive analysis reports.

Example:
    >>> from oscura.visualization import batch
    >>> trace = osc.load("signal.wfm")
    >>> plots = batch.generate_all_plots(trace)
    >>> # Returns: {"waveform": <base64>, "fft": <base64>, ...}
"""

from __future__ import annotations

import base64
from io import BytesIO
from typing import TYPE_CHECKING

import matplotlib

matplotlib.use("Agg")  # Non-interactive backend
import matplotlib.pyplot as plt

from oscura.core.types import DigitalTrace, WaveformTrace

if TYPE_CHECKING:
    from matplotlib.figure import Figure

# Plot configuration
PLOT_DPI = 150
FIGURE_SIZE = (10, 6)


def fig_to_base64(fig: Figure, *, dpi: int = PLOT_DPI) -> str:
    """Convert matplotlib figure to base64-encoded PNG.

    Args:
        fig: Matplotlib figure object.
        dpi: Resolution in dots per inch.

    Returns:
        Base64-encoded PNG image string with data URI prefix.

    Example:
        >>> fig, ax = plt.subplots()
        >>> ax.plot([1, 2, 3])
        >>> b64 = fig_to_base64(fig)
    """
    buf = BytesIO()
    fig.savefig(buf, format="png", dpi=dpi, bbox_inches="tight", facecolor="white")
    buf.seek(0)
    img_base64 = base64.b64encode(buf.read()).decode("utf-8")
    plt.close(fig)
    return f"data:image/png;base64,{img_base64}"


def generate_all_plots(
    trace: WaveformTrace | DigitalTrace,
    *,
    verbose: bool = True,
) -> dict[str, str]:
    """Generate all applicable plots for a signal trace.

    Automatically detects signal type and generates appropriate plots:
    - Analog: waveform, FFT, histogram, spectrogram
    - Digital: waveform, timing diagram

    Args:
        trace: WaveformTrace or DigitalTrace to visualize.
        verbose: Print progress messages.

    Returns:
        Dictionary mapping plot names to base64 image strings.

    Example:
        >>> trace = osc.load("signal.wfm")
        >>> plots = generate_all_plots(trace)
        >>> len(plots)  # 4-5 plots for analog signal
        4
    """
    from oscura.visualization.plot import (
        plot_fft,
        plot_histogram,
        plot_spectrogram,
        plot_timing,
        plot_waveform,
    )

    plots = {}

    # Always generate waveform (handle both analog and digital)
    try:
        fig, ax = plt.subplots(figsize=FIGURE_SIZE)
        if isinstance(trace, WaveformTrace):
            plot_waveform(ax, trace)
        else:
            # Digital trace
            plot_timing(ax, trace)
        plots["waveform"] = fig_to_base64(fig)
        if verbose:
            print("  ✓ Generated waveform plot")
    except Exception as e:
        if verbose:
            print(f"  ⚠ Waveform plot failed: {e}")

    if isinstance(trace, WaveformTrace):
        # FFT spectrum
        try:
            fig, ax = plt.subplots(figsize=FIGURE_SIZE)
            plot_fft(ax, trace)
            plots["fft"] = fig_to_base64(fig)
            if verbose:
                print("  ✓ Generated FFT spectrum")
        except Exception as e:
            if verbose:
                print(f"  ⚠ FFT plot failed: {e}")

        # Histogram
        try:
            fig, ax = plt.subplots(figsize=FIGURE_SIZE)
            plot_histogram(ax, trace.data)
            plots["histogram"] = fig_to_base64(fig)
            if verbose:
                print("  ✓ Generated histogram")
        except Exception as e:
            if verbose:
                print(f"  ⚠ Histogram plot failed: {e}")

        # Spectrogram
        try:
            fig, ax = plt.subplots(figsize=FIGURE_SIZE)
            plot_spectrogram(ax, trace)
            plots["spectrogram"] = fig_to_base64(fig)
            if verbose:
                print("  ✓ Generated spectrogram")
        except Exception as e:
            if verbose:
                print(f"  ⚠ Spectrogram plot failed: {e}")

    elif isinstance(trace, DigitalTrace):
        # Timing diagram
        try:
            fig, ax = plt.subplots(figsize=FIGURE_SIZE)
            plot_timing(ax, trace)
            plots["timing"] = fig_to_base64(fig)
            if verbose:
                print("  ✓ Generated timing diagram")
        except Exception as e:
            if verbose:
                print(f"  ⚠ Timing plot failed: {e}")

    return plots


__all__ = [
    "FIGURE_SIZE",
    "PLOT_DPI",
    "fig_to_base64",
    "generate_all_plots",
]
