"""SQLAlchemy implementation of VoiceLibraryRepository."""

from __future__ import annotations

from typing import List, Optional

from sqlalchemy.orm import Session

from packages.adapters.sqlalchemy_impl.models import VoiceLibraryModel
from packages.domain.voice_library import VoiceLibraryItem


class SQLAlchemyVoiceLibraryRepository:
    """SQLAlchemy 配音库仓储"""

    def __init__(self, session: Session) -> None:
        self.session = session

    def list_by_user(
        self,
        user_id: str,
        *,
        status: Optional[str] = None,
        skip: int = 0,
        limit: int = 50,
    ) -> List[VoiceLibraryItem]:
        query = self.session.query(VoiceLibraryModel).filter(
            VoiceLibraryModel.user_id == user_id,
        )
        if status:
            query = query.filter(VoiceLibraryModel.status == status)
        query = query.order_by(VoiceLibraryModel.created_at.desc())
        models = query.offset(skip).limit(limit).all()
        return [self._model_to_entity(m) for m in models]

    def get(self, voice_id: str, user_id: str) -> Optional[VoiceLibraryItem]:
        model = (
            self.session.query(VoiceLibraryModel)
            .filter(
                VoiceLibraryModel.id == voice_id,
                VoiceLibraryModel.user_id == user_id,
            )
            .first()
        )
        if model is None:
            return None
        return self._model_to_entity(model)

    def create(self, item: VoiceLibraryItem) -> VoiceLibraryItem:
        model = VoiceLibraryModel(
            id=item.id,
            user_id=item.user_id,
            project_id=item.project_id or "",
            name=item.name,
            text=item.text,
            voice_provider=item.voice_provider,
            voice_id=item.voice_id,
            voice_name=item.voice_name,
            audio_url=item.audio_url,
            duration=item.duration,
            file_size=item.file_size,
            status=item.status,
            tags=item.tags,
            extra_meta=item.metadata_,
        )
        self.session.add(model)
        self.session.commit()
        self.session.refresh(model)
        return self._model_to_entity(model)

    def update(self, item: VoiceLibraryItem) -> VoiceLibraryItem:
        model = (
            self.session.query(VoiceLibraryModel)
            .filter(
                VoiceLibraryModel.id == item.id,
                VoiceLibraryModel.user_id == item.user_id,
            )
            .first()
        )
        if model is None:
            raise ValueError(f"VoiceLibraryItem {item.id} not found")
        model.name = item.name
        model.text = item.text
        model.voice_provider = item.voice_provider
        model.voice_id = item.voice_id
        model.voice_name = item.voice_name
        model.audio_url = item.audio_url
        model.duration = item.duration
        model.file_size = item.file_size
        model.status = item.status
        model.tags = item.tags
        model.extra_meta = item.metadata_
        self.session.commit()
        self.session.refresh(model)
        return self._model_to_entity(model)

    def delete(self, voice_id: str, user_id: str) -> bool:
        model = (
            self.session.query(VoiceLibraryModel)
            .filter(
                VoiceLibraryModel.id == voice_id,
                VoiceLibraryModel.user_id == user_id,
            )
            .first()
        )
        if model is None:
            return False
        # Soft delete by setting status to deleted
        model.status = "deleted"
        self.session.commit()
        return True

    def count_by_user(self, user_id: str, *, status: Optional[str] = None) -> int:
        query = self.session.query(VoiceLibraryModel).filter(
            VoiceLibraryModel.user_id == user_id,
            VoiceLibraryModel.status != "deleted",
        )
        if status:
            query = query.filter(VoiceLibraryModel.status == status)
        return query.count()

    @staticmethod
    def _model_to_entity(model: VoiceLibraryModel) -> VoiceLibraryItem:
        return VoiceLibraryItem(
            id=model.id,
            user_id=model.user_id,
            name=model.name,
            text=model.text,
            voice_provider=model.voice_provider,
            voice_id=model.voice_id,
            voice_name=model.voice_name,
            audio_url=model.audio_url,
            duration=model.duration or 0,
            file_size=model.file_size or 0,
            status=model.status,
            project_id=model.project_id if model.project_id else None,
            tags=model.tags or [],
            metadata_=model.extra_meta or {},
            created_at=model.created_at,
            updated_at=model.updated_at,
        )
