"""Logs 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.logs.models import ProjectLogConfig, ProjectLogDrain


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

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

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

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


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

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

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

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

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

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

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