"""Audio adapter for get笔记录音卡.

Polls user's get笔 recording cloud (or local filesystem) for new audio files,
then triggers audio_processor to transcribe + diarize them into JSONL.

Assumes:
- Audio files are stored in a known local path (e.g., ~/Downloads/getbi/)
- Or get笔 provides a simple web API (e.g., GET /api/v1/recordings?since=...)
- Audio processor is installed and available as `audio_processor` CLI.

This adapter emits messages via the standard gateway flow:
  -> inbound_handler.py -> db.py -> router.py

Implements BaseAdapter interface.
"""

import json
import logging
import os
import subprocess
import time
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Dict, List, Optional

from src.agentgate_gateway.adapters.base import ChannelAdapter

logger = logging.getLogger(__name__)


class AudioAdapter(ChannelAdapter):
    """Adapter for ingesting audio from get笔记录音卡."""

    def __init__(self, config: Dict[str, Any]):
        super().__init__("audio", None)  # no on_message — handled by inbound_handler
        self.audio_dir = Path(
            config.get("audio_dir", "~/Downloads/getbi/")
        ).expanduser()
        self.last_check = 0.0  # Unix timestamp
        self.processor_cmd = config.get("processor_cmd", "audio_processor")

    async def start(self) -> None:
        pass

    async def stop(self) -> None:
        pass

    async def _real_send_message(self, chat_id: str, text: str) -> bool:
        raise NotImplementedError("AudioAdapter is poll-only, not message-sending")

    def _real_is_connected(self) -> bool:
        return self.audio_dir.exists()

    def poll(self) -> List[Dict[str, Any]]:
        """Find new audio files and trigger processing.

        Returns list of message dicts ready for inbound_handler.
        Each dict must contain at minimum:
          - 'type': 'user'
          - 'message': { 'content': [...] }
          - 'timestamp': ISO string
          - 'sessionId': unique string (e.g., 'audio_YYYYMMDD_HHMMSS')
        """
        if not self.audio_dir.exists():
            logger.warning(f"Audio directory does not exist: {self.audio_dir}")
            return []

        # Find new .m4a, .mp3, .wav files modified since last check
        now = time.time()
        new_files = [
            f
            for f in self.audio_dir.rglob("*.*")
            if f.is_file()
            and f.suffix.lower() in (".m4a", ".mp3", ".wav", ".aac")
            and f.stat().st_mtime > self.last_check
        ]

        messages = []
        for audio_path in sorted(new_files):
            try:
                # Generate sessionId from timestamp + filename
                ts = datetime.fromtimestamp(audio_path.stat().st_mtime, tz=timezone.utc)
                session_id = (
                    f"audio_{ts.strftime('%Y%m%d_%H%M%S')}_{audio_path.stem[:8]}"
                )

                # Invoke audio_processor CLI
                result = subprocess.run(
                    [self.processor_cmd, str(audio_path)],
                    capture_output=True,
                    text=True,
                    timeout=600,  # 10 minutes max
                )

                if result.returncode != 0:
                    logger.error(
                        f"audio_processor failed on {audio_path}: {result.stderr[:200]}"
                    )
                    continue

                # Expect JSONL output — one per line
                for line_num, line in enumerate(result.stdout.strip().split("\n"), 1):
                    if not line.strip():
                        continue
                    try:
                        entry = json.loads(line)
                        # Enrich with mandatory fields if missing
                        entry.setdefault("sessionId", session_id)
                        entry.setdefault(
                            "timestamp", datetime.now(timezone.utc).isoformat()
                        )
                        messages.append(entry)
                    except json.JSONDecodeError as e:
                        logger.warning(
                            f"Invalid JSONL line {line_num} from {audio_path}: {e}"
                        )
                        continue

            except Exception as e:
                logger.exception(f"Failed to process {audio_path}: {e}")
                continue

        self.last_check = now
        return messages

    def close(self):
        pass

    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        return {
            "audio_dir": {
                "type": "string",
                "default": "~/Downloads/getbi/",
                "description": "Local directory containing downloaded get笔 recordings",
            },
            "processor_cmd": {
                "type": "string",
                "default": "audio_processor",
                "description": "Path to audio_processor CLI binary or script",
            },
        }
