"""Chunk processor for large file handling."""

import logging
from pathlib import Path
from typing import Any, Dict, List, Optional

from .processor_types import AsyncProcessor

logger = logging.getLogger(__name__)


class ChunkProcessor(AsyncProcessor):
    """Process large files in chunks with overlap.

    Handles splitting large audio files into manageable chunks
    for processing with configurable overlap.
    """

    def __init__(self, name: str = "ChunkProcessor", config: Optional[Dict[str, Any]] = None):
        """Initialize chunk processor.

        Args:
            name: Processor name
            config: Processor configuration

        """
        super().__init__(name, config)

        # Chunking settings
        self.chunk_duration = config.get("chunk_duration", 600) if config else 600  # 10 minutes
        self.overlap_duration = config.get("overlap", 2) if config else 2  # 2 seconds
        self.max_chunks = config.get("max_chunks", 100) if config else 100

    async def create_chunks(self, audio_path: Path, duration: float) -> List[Dict[str, Any]]:
        """Create chunk definitions for an audio file.

        Args:
            audio_path: Path to audio file
            duration: Total duration in seconds

        Returns:
            List of chunk definitions

        """
        chunks = []
        chunk_size = self.chunk_duration
        step = chunk_size - self.overlap_duration

        for i, start in enumerate(range(0, int(duration), step)):
            if i >= self.max_chunks:
                logger.warning(f"Reached maximum chunks ({self.max_chunks})")
                break

            end = min(start + chunk_size, duration)

            chunks.append(
                {
                    "index": i,
                    "start": start,
                    "end": end,
                    "duration": end - start,
                    "path": audio_path,
                    "output_path": audio_path.parent
                    / f"{audio_path.stem}_chunk_{i:03d}{audio_path.suffix}",
                }
            )

            if end >= duration:
                break

        return chunks

    async def extract_chunk(self, chunk_def: Dict[str, Any]) -> Path:
        """Extract a specific chunk from audio file.

        Args:
            chunk_def: Chunk definition with start, end, paths

        Returns:
            Path to extracted chunk

        """
        # In real implementation, would use FFmpeg to extract chunk
        # For now, return a placeholder
        logger.info(
            f"Extracting chunk {chunk_def['index']}: {chunk_def['start']}-{chunk_def['end']}s"
        )

        # Simulate extraction
        output_path = chunk_def["output_path"]
        output_path.touch()  # Create empty file as placeholder

        return output_path

    async def merge_results(self, chunk_results: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Merge results from processed chunks.

        Args:
            chunk_results: List of results from each chunk

        Returns:
            Merged result with overlap handling

        """
        if not chunk_results:
            return {"segments": [], "text": ""}

        # Sort by chunk index
        chunk_results.sort(key=lambda x: x.get("chunk_index", 0))

        merged = {
            "segments": [],
            "text": "",
            "chunks_processed": len(chunk_results),
        }

        # Merge segments with overlap handling
        for i, chunk in enumerate(chunk_results):
            segments = chunk.get("segments", [])

            if i > 0 and self.overlap_duration > 0:
                # Remove overlapping segments from beginning
                overlap_start = chunk.get("start", 0)
                segments = [
                    s
                    for s in segments
                    if s.get("start", 0) >= overlap_start + self.overlap_duration / 2
                ]

            merged["segments"].extend(segments)

        # Reconstruct full text
        merged["text"] = " ".join(s.get("text", "") for s in merged["segments"])

        return merged

    async def process_async(self, data: Any) -> Any:
        """Async processing interface from base class.

        Args:
            data: Input data (audio path and duration)

        Returns:
            Chunk definitions or merged results

        """
        if isinstance(data, tuple):
            if len(data) == 2:
                # Create chunks
                audio_path, duration = data
                return await self.create_chunks(Path(audio_path), duration)
            elif len(data) == 1 and isinstance(data[0], list):
                # Merge results
                return await self.merge_results(data[0])

        raise TypeError(f"Expected tuple of (path, duration) or (results,), got {type(data)}")
