import logging
import os

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

try:
    from python_sidecar.ai.analyzer import RecordingAnalyzer
except ImportError as import_error:
    RecordingAnalyzer = None  # type: ignore[assignment]
    ANALYZER_IMPORT_ERROR = import_error
else:
    ANALYZER_IMPORT_ERROR = None

try:
    from python_sidecar.ai.copy_assistant import CopyAssistant
except ImportError as import_error:
    CopyAssistant = None  # type: ignore[assignment]
    COPY_ASSIST_IMPORT_ERROR = import_error
else:
    COPY_ASSIST_IMPORT_ERROR = None

logger = logging.getLogger(__name__)
router = APIRouter()


class AnalysisRequest(BaseModel):
    session_dir: str
    api_key: str | None = None


class LocalizeCopyRequest(BaseModel):
    text: str
    target_language: str
    source_language: str | None = None
    api_key: str | None = None


class LocalizeCopyResponse(BaseModel):
    text: str
    target_language: str


class VoiceoverScriptRequest(BaseModel):
    text: str
    language: str | None = None
    tone: str | None = None
    max_seconds: int = 12
    api_key: str | None = None


class VoiceoverScriptResponse(BaseModel):
    script: str
    language: str | None = None
    tone: str | None = None


def _normalize_text(value: str, *, field_name: str, max_chars: int = 8000) -> str:
    normalized = value.strip()
    if not normalized:
        raise HTTPException(status_code=400, detail=f"{field_name} is required")
    if len(normalized) > max_chars:
        raise HTTPException(status_code=400, detail=f"{field_name} exceeds {max_chars} characters")
    return normalized


def _normalize_language(value: str, *, field_name: str) -> str:
    normalized = value.strip()
    if not normalized:
        raise HTTPException(status_code=400, detail=f"{field_name} is required")
    if len(normalized) > 48:
        raise HTTPException(status_code=400, detail=f"{field_name} exceeds 48 characters")
    return normalized


def _optional_text(value: str | None, *, max_chars: int = 120) -> str | None:
    if value is None:
        return None
    normalized = value.strip()
    if not normalized:
        return None
    return normalized[:max_chars]


def _require_copy_assistant() -> type[CopyAssistant]:
    if CopyAssistant is None:
        message = "AI copy assistant unavailable: optional dependency missing"
        if COPY_ASSIST_IMPORT_ERROR is not None:
            message = f"{message} ({COPY_ASSIST_IMPORT_ERROR})"
        raise HTTPException(status_code=503, detail=message)
    return CopyAssistant


@router.post("/analyze")
async def analyze_recording(request: AnalysisRequest):
    events_path = os.path.join(request.session_dir, "events.ndjson")
    if not os.path.exists(events_path):
        raise HTTPException(status_code=404, detail="Events file not found")

    if RecordingAnalyzer is None:
        message = "Analysis unavailable: optional dependency missing"
        if ANALYZER_IMPORT_ERROR is not None:
            message = f"{message} ({ANALYZER_IMPORT_ERROR})"
        raise HTTPException(status_code=503, detail=message)

    try:
        analyzer = RecordingAnalyzer(api_key=request.api_key)
        results = analyzer.analyze_recording(events_path)

        # Save results to session metadata
        metadata_path = os.path.join(request.session_dir, "analysis.json")
        with open(metadata_path, "w") as f:
            import json

            json.dump(results, f, indent=2)

        return results
    except Exception as e:
        logger.exception("Analysis failed for session %s", request.session_dir)
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/localize-copy", response_model=LocalizeCopyResponse)
async def localize_copy(request: LocalizeCopyRequest) -> LocalizeCopyResponse:
    copy_assistant_cls = _require_copy_assistant()
    source_text = _normalize_text(request.text, field_name="text")
    target_language = _normalize_language(
        request.target_language, field_name="target_language"
    )
    source_language = _optional_text(request.source_language, max_chars=48)

    try:
        assistant = copy_assistant_cls(api_key=request.api_key)
        localized = assistant.localize_text(
            text=source_text,
            target_language=target_language,
            source_language=source_language,
        )
        return LocalizeCopyResponse(text=localized, target_language=target_language)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e)) from e
    except RuntimeError as e:
        raise HTTPException(status_code=500, detail=str(e)) from e
    except Exception as e:
        logger.exception("Localization failed")
        raise HTTPException(status_code=500, detail=f"Localization failed: {e}") from e


@router.post("/voiceover-script", response_model=VoiceoverScriptResponse)
async def generate_voiceover_script(
    request: VoiceoverScriptRequest,
) -> VoiceoverScriptResponse:
    copy_assistant_cls = _require_copy_assistant()
    source_text = _normalize_text(request.text, field_name="text")
    language = _optional_text(request.language, max_chars=48)
    tone = _optional_text(request.tone, max_chars=120)
    max_seconds = max(4, min(45, request.max_seconds))

    try:
        assistant = copy_assistant_cls(api_key=request.api_key)
        script = assistant.generate_voiceover_script(
            text=source_text,
            language=language,
            tone=tone,
            max_seconds=max_seconds,
        )
        return VoiceoverScriptResponse(script=script, language=language, tone=tone)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e)) from e
    except RuntimeError as e:
        raise HTTPException(status_code=500, detail=str(e)) from e
    except Exception as e:
        logger.exception("Voiceover generation failed")
        raise HTTPException(status_code=500, detail=f"Voiceover generation failed: {e}") from e
