"""
Base seeder class for database seeding operations.
"""

from abc import ABC, abstractmethod
from sqlalchemy.orm import Session
from src.core.database import SessionLocal
from typing import Generator
import logging

logger = logging.getLogger(__name__)


class BaseSeeder(ABC):
    """
    Abstract base class for database seeders.
    
    Provides common functionality for seeding operations including
    session management and error handling.
    """
    
    def __init__(self):
        """Initialize the seeder."""
        self.name = self.__class__.__name__
    
    def get_session(self) -> Generator[Session, None, None]:
        """
        Get a database session for seeding operations.
        
        Yields:
            Database session
        """
        db = SessionLocal()
        try:
            yield db
        except Exception as e:
            logger.error(f"Error in seeder {self.name}: {e}")
            db.rollback()
            raise
        finally:
            db.close()
    
    @abstractmethod
    def seed(self, db: Session) -> None:
        """
        Abstract method to implement seeding logic with a provided session.
        
        Args:
            db: Database session to use for seeding operations
        """
        pass
    
    def run(self) -> None:
        """
        Run the seeder with proper session management and error handling.
        """
        logger.info(f"Running seeder: {self.name}")
        
        try:
            with next(self.get_session()) as db:
                # Check if seeder should run
                if not self.should_run(db):
                    logger.info(f"Skipping seeder {self.name} (conditions not met)")
                    return
                
                self.seed(db)
                db.commit()
                logger.info(f"Seeder {self.name} completed successfully")
        except Exception as e:
            logger.error(f"Seeder {self.name} failed: {e}")
            raise
    
    def should_run(self, db: Session) -> bool:
        """
        Determine if the seeder should run.
        
        Override this method to implement conditional seeding logic.
        
        Args:
            db: Database session
            
        Returns:
            True if the seeder should run, False otherwise
        """
        return True
