'''
Seeder Module

This module provides the core functionality for generating and inserting
synthetic data into Django models. It is designed to simplify database
seeding during development and testing by automatically generating
structured datasets and converting them into Django ORM model instances.

Information
-----------
@author: Christian G. Garcia
@github: github.com/christiangarcia0311/django-model-seeder
'''


from seed import Dataset
from django.db.models import Model 
from typing import Dict, List, Type, Any, Callable


class ModelSeeder:
    
    def __init__(self, model: Type[Model]):
        self.model = model
        self.dataset = Dataset()
        self.field_mapping = {}
        
        self._introspect_fields()
        
    def _introspect_fields(self):
        for field in self.model._meta.get_fields():
            if field.many_to_one or field.one_to_one or field.primary_key:
                continue
            
            self.field_mapping[field.name] = None 
            
    def seed(self, rows: int, mapping: Dict[str, Any]) -> List[Model]:
        data_generator = self.dataset.generate(rows, mapping)
        
        instances = []
        
        for index, row in data_generator.iterrows():
            kwargs = {}

            for field_name, value in row.to_dict().items():
                if field_name in self.field_mapping:
                    kwargs[field_name] = value
                    
            instance = self.model(**kwargs)
            instances.append(instance)
            
        self.model.objects.bulk_create(instances)
        return instances
    
    def seed_with_relations(
        self,
        rows: int,
        mapping: Dict[str, Any],
        relations: Dict[str, Callable] = None 
    ) -> List[Model]:
        data_generator = self.dataset.generate(rows, mapping)
        
        instances = []
        
        for index, row in data_generator.iterrows():
            kwargs = {}
            
            for field_name, value in row.to_dict().items():
                if field_name in self.field_mapping:
                    kwargs[field_name] = value
                
            if relations:
                for relation_field, resolver_func in relations.items():
                    try:
                        kwargs[relation_field] = resolver_func()
                    except Exception as e:
                        print(f'Warning: Could not resolve relation {relation_field}: {e}')
                        continue 
                    
            instance = self.model(**kwargs)
            instances.append(instance)
        
        self.model.objects.bulk_create(instances)
        return instances 
    
    def seed_with_validation(
        self,
        rows: int,
        mapping: Dict[str, Any],
        validator: Callable = None 
    ) -> List[Model]:
        data_generator = self.dataset.generate(rows, mapping)
        
        instances = []
        
        for index, row in data_generator.iterrows():
            kwargs = {}
            
            for field_name, value in row.to_dict().items():
                if field_name in self.field_mapping:
                    kwargs[field_name] = value
                    
            if validator and not validator(kwargs):
                continue 
            
            instance = self.model(**kwargs)
            instances.append(instance)
        
        self.model.objects.bulk_create(instances)
        return instances 
    


