# ================================================================
# services/procurement/app/repositories/base_repository.py
# ================================================================
"""
Base Repository Pattern for Procurement Service
"""

from typing import Generic, TypeVar, Type, Optional, List, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from shared.database.base import Base

ModelType = TypeVar("ModelType", bound=Base)


class BaseRepository(Generic[ModelType]):
    """Base repository with common database operations"""

    def __init__(self, model: Type[ModelType]):
        self.model = model

    async def get_by_id(self, db: AsyncSession, id: Any) -> Optional[ModelType]:
        """Get entity by ID"""
        result = await db.execute(select(self.model).where(self.model.id == id))
        return result.scalar_one_or_none()

    async def get_all(self, db: AsyncSession, skip: int = 0, limit: int = 100) -> List[ModelType]:
        """Get all entities with pagination"""
        result = await db.execute(select(self.model).offset(skip).limit(limit))
        return result.scalars().all()

    async def create(self, db: AsyncSession, **kwargs) -> ModelType:
        """Create new entity"""
        instance = self.model(**kwargs)
        db.add(instance)
        await db.flush()
        await db.refresh(instance)
        return instance

    async def update(self, db: AsyncSession, id: Any, **kwargs) -> Optional[ModelType]:
        """Update entity"""
        instance = await self.get_by_id(db, id)
        if not instance:
            return None

        for key, value in kwargs.items():
            if hasattr(instance, key):
                setattr(instance, key, value)

        await db.flush()
        await db.refresh(instance)
        return instance

    async def delete(self, db: AsyncSession, id: Any) -> bool:
        """Delete entity"""
        instance = await self.get_by_id(db, id)
        if not instance:
            return False

        await db.delete(instance)
        await db.flush()
        return True
