import uuid
from collections.abc import Sequence
from typing import Any

from sqlalchemy import delete, func, select
from sqlalchemy.ext.asyncio import AsyncSession

from src.domain.entities import ConnectorConfigEntity
from src.domain.interfaces import IConnectorConfigRepository
from src.infrastructure.database.models import ConnectorConfigModel


def _model_to_entity(m: ConnectorConfigModel) -> ConnectorConfigEntity:
    return ConnectorConfigEntity(
        id=m.id,
        connector_id=m.connector_id,
        key=m.key,
        value=m.value,
        encrypted=m.encrypted,
        description=m.description,
        created_at=m.created_at,
        updated_at=m.updated_at,
    )


class ConnectorConfigRepository(IConnectorConfigRepository):
    def __init__(self, session: AsyncSession) -> None:
        self._session = session

    async def list_by_connector(self, connector_id: uuid.UUID) -> Sequence[ConnectorConfigEntity]:
        stmt = select(ConnectorConfigModel).where(ConnectorConfigModel.connector_id == connector_id).order_by(ConnectorConfigModel.key)
        result = await self._session.execute(stmt)
        models = result.scalars().all()
        return [_model_to_entity(m) for m in models]

    async def get_by_key(self, connector_id: uuid.UUID, key: str) -> ConnectorConfigEntity | None:
        stmt = select(ConnectorConfigModel).where(
            ConnectorConfigModel.connector_id == connector_id,
            ConnectorConfigModel.key == key,
        )
        result = await self._session.execute(stmt)
        model = result.scalar_one_or_none()
        return _model_to_entity(model) if model else None

    async def upsert(self, entity: ConnectorConfigEntity) -> ConnectorConfigEntity:
        existing = await self.get_by_key(entity.connector_id, entity.key)
        if existing:
            stmt = (
                ConnectorConfigModel.__table__.update()
                .where(ConnectorConfigModel.id == existing.id)
                .values(value=entity.value, encrypted=entity.encrypted, description=entity.description)
            )
            await self._session.execute(stmt)
            await self._session.flush()
            return await self.get_by_key(entity.connector_id, entity.key)  # type: ignore[return-value]
        else:
            model = ConnectorConfigModel(
                connector_id=entity.connector_id,
                key=entity.key,
                value=entity.value,
                encrypted=entity.encrypted,
                description=entity.description,
            )
            self._session.add(model)
            await self._session.flush()
            return _model_to_entity(model)

    async def delete(self, config_id: uuid.UUID) -> bool:
        stmt = delete(ConnectorConfigModel).where(ConnectorConfigModel.id == config_id)
        result = await self._session.execute(stmt)
        return result.rowcount > 0
