"""External Connections domain — data access layer."""
from __future__ import annotations

from typing import Optional
from uuid import UUID, uuid4

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from src.domain.external_connections.models import ProjectExternalConnection


class ExternalConnectionRepository:
    def __init__(self, db: AsyncSession) -> None:
        self._db = db

    async def list_for_project(
        self, project_id: UUID
    ) -> list[ProjectExternalConnection]:
        result = await self._db.execute(
            select(ProjectExternalConnection)
            .where(ProjectExternalConnection.project_id == project_id)
            .order_by(ProjectExternalConnection.name)
        )
        return list(result.scalars().all())

    async def get_by_name(
        self, project_id: UUID, name: str
    ) -> Optional[ProjectExternalConnection]:
        result = await self._db.execute(
            select(ProjectExternalConnection).where(
                ProjectExternalConnection.project_id == project_id,
                ProjectExternalConnection.name == name,
            )
        )
        return result.scalar_one_or_none()

    async def get_by_id(self, connection_id: UUID) -> Optional[ProjectExternalConnection]:
        result = await self._db.execute(
            select(ProjectExternalConnection).where(
                ProjectExternalConnection.id == connection_id
            )
        )
        return result.scalar_one_or_none()

    async def create(self, **fields) -> ProjectExternalConnection:
        row = ProjectExternalConnection(id=uuid4(), **fields)
        self._db.add(row)
        await self._db.flush()
        return row

    async def update(
        self, row: ProjectExternalConnection, **fields
    ) -> ProjectExternalConnection:
        for k, v in fields.items():
            setattr(row, k, v)
        await self._db.flush()
        return row

    async def delete(self, row: ProjectExternalConnection) -> None:
        await self._db.delete(row)
        await self._db.flush()

    async def count_for_project(self, project_id: UUID) -> int:
        from sqlalchemy import func
        result = await self._db.execute(
            select(func.count()).where(
                ProjectExternalConnection.project_id == project_id
            )
        )
        return result.scalar_one()
