"""SuperTonic Engine adapter for the TTS Plugin Architecture.

This module adapts the existing SuperTonic backend to the new Engine/EngineSession
protocol. It wraps the SupertonicPipeline without modifying it.
"""

from __future__ import annotations

import io
import logging
from typing import Any

import numpy as np

from abogen.tts_plugin.capabilities import VoiceLister
from abogen.tts_plugin.engine import Engine, EngineSession
from abogen.tts_plugin.errors import EngineError
from abogen.tts_plugin.manifest import VoiceManifest
from abogen.tts_plugin.types import (
    AudioFormat,
    Duration,
    SynthesisRequest,
    SynthesizedAudio,
)

logger = logging.getLogger(__name__)

# Sample rate for SuperTonic audio
_SUPERTONIC_SAMPLE_RATE = 24000


class SuperTonicSession:
    """EngineSession implementation for SuperTonic.

    Owns mutable execution state for synthesis.
    NOT thread-safe.
    """

    def __init__(self, pipeline: Any) -> None:
        self._pipeline = pipeline
        self._disposed = False

    def synthesize(self, request: SynthesisRequest) -> SynthesizedAudio:
        """Synthesize audio from text using SuperTonic."""
        if self._disposed:
            raise EngineError("Session disposed")

        try:
            import soundfile as sf

            voice = request.voice.key
            speed = float(request.parameters.values.get("speed", 1.0))
            total_steps = request.parameters.values.get("total_steps", None)
            split_pattern = request.parameters.values.get("split_pattern", None)

            if total_steps is not None:
                total_steps = int(total_steps)

            audio_parts: list[np.ndarray] = []
            for segment in self._pipeline(
                request.text,
                voice=voice,
                speed=speed,
                split_pattern=split_pattern,
                total_steps=total_steps,
            ):
                audio_parts.append(segment.audio)

            if not audio_parts:
                return SynthesizedAudio(
                    data=b"",
                    format=AudioFormat(mime="audio/wav", extension="wav"),
                    duration=Duration(seconds=0.0),
                )

            combined = np.concatenate(audio_parts).astype("float32", copy=False)
            buf = io.BytesIO()
            sf.write(buf, combined, self._pipeline.sample_rate, format="WAV")
            audio_bytes = buf.getvalue()
            duration_seconds = len(combined) / self._pipeline.sample_rate

            return SynthesizedAudio(
                data=audio_bytes,
                format=AudioFormat(mime="audio/wav", extension="wav"),
                duration=Duration(seconds=duration_seconds),
            )
        except EngineError:
            raise
        except Exception as e:
            raise EngineError(f"Synthesis failed: {e}") from e

    def dispose(self) -> None:
        """Release session resources. Idempotent."""
        self._disposed = True


class SuperTonicEngine:
    """Engine implementation for SuperTonic.

    Factory for SuperTonicSession instances. Stateless and thread-safe.
    """

    def __init__(self, pipeline: Any) -> None:
        self._pipeline = pipeline
        self._disposed = False

    def createSession(self) -> SuperTonicSession:
        """Create a new SuperTonicSession."""
        if self._disposed:
            raise EngineError("Engine disposed")
        return SuperTonicSession(self._pipeline)

    def dispose(self) -> None:
        """Release engine resources. Idempotent."""
        self._disposed = True

    def listVoices(self, sourceId: str) -> list[VoiceManifest]:
        """List available SuperTonic voices. Implements VoiceLister capability.
        
        Note: Static voice catalog is declared in plugin manifest.
        This method is retained for VoiceLister interface compliance.
        """
        if self._disposed:
            raise EngineError("Engine disposed")
        return []
