'''
Loaders module

Provides a bulk loader utility for registering Django models and
executing seed operations using ModelSeeder instances

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

from django.apps import apps 
from django.db.models import Model
from typing import Dict, List, Type, Any, Callable
from .seeder import ModelSeeder


class BulkModelLoader:
    
    def __init__(self):
        self.seeders = {}
        self.results = {}
        
    def register(self, model: Type[Model])-> ModelSeeder:
        seeder = ModelSeeder(model)
        self.seeders[model.__name__] = seeder 
        return seeder 
    
    def load_model(self, app_label: str, model_name: str) -> ModelSeeder:
        model = apps.get_model(app_label, model_name)
        return self.register(model)
    
    def seed_all(
        self,
        configurations: Dict[str, Dict[str, Any]],
        relations_map: Dict[str, Dict[str, Callable]] = None
    ) -> Dict[str, List[Model]]:
        
        relations_map = relations_map or {}
        results = {}
        
        for model_name, config in configurations.items():
            if model_name in self.seeders:
                seeder = self.seeders[model_name]
                rows = config.get('rows', 10)
                mapping = config.get('mapping', {})
                relations = relations_map.get(model_name, {})
                
                if relations:
                    results[model_name] = seeder.seed_with_relations(rows, mapping, relations)
                else:
                    results[model_name] = seeder.seed(rows, mapping)
                
                self.results[model_name] = results[model_name]
        
        return results 
    
    def seed_model(self, model_name: str, rows: int, mapping: Dict[str, Any]) -> List[Model]:
        if model_name in self.seeders:
            result = self.seeders[model_name].seed(rows, mapping, relations_map=None)
            self.results[model_name] = result
            return result
        return []
    
    def get_results(self, model_name: str = None) -> Dict[str, List[Model]] | List[Model]:
        if model_name:
            return self.results.get(model_name, [])
        return self.results
    
    def clear(self, model_name: str = None):
        if model_name and model_name in self.seeders:
            self.seeders[model_name].model.objects.all().delete()
            
            if model_name in self.results:
                del self.results[model_name]
        else:
            for seeder in self.seeders.values():
                seeder.model.objects.all().delete()
            self.results.clear()
            
    def list_models(self) -> List[str]:
        return list(self.seeders.keys())
        