from django.db import models
from django.utils import timezone
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.db import transaction

from ..registry import model_registry
import uuid

from . import ModelLog, BaseModel
import logging

logger = logging.getLogger(__name__)

class DataAccess(BaseModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    shared_with = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='shared_data')
    model_name = models.CharField(max_length=50)
    model_id = models.UUIDField()
    store_id = models.CharField(max_length=100, default="", blank=True, null=True) # a value matching LeStorage directory sub-stores. Matches the name of the directory.
    granted_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = "Data Access"

    def delete_dependencies(self):
        pass

    def create_revoke_access_log(self):
        self.create_access_log(self.shared_with.all(), 'REVOKED_ACCESS')

    def concerned_users(self):
        users = list(self.shared_with.all())
        if self.related_user:
            users.append(self.related_user)
        return users

    def create_access_log(self, users, operation):
        """Create an access log for a list of users """
        model_class = model_registry.get_model(self.model_name)
        if model_class:
            for user in users:
                logger.info(f'=== create ModelLog for: {operation} > {users}')
                ModelLog.objects.create(
                    user=user,
                    model_id=self.model_id,
                    model_name=self.model_name,
                    operation=operation,
                    date=timezone.now(),
                    store_id=self.store_id
                )

                # existing_log = ModelLog.objects.filter(user=user, model_id=self.model_id, operation=operation).first()
                # if existing_log:
                #     existing_log.date = timezone.now()
                #     existing_log.model_operation = operation
                #     existing_log.save()
                # else:
                #     ModelLog.objects.create(
                #         user=user,
                #         model_id=self.model_id,
                #         model_name=self.model_name,
                #         operation=operation,
                #         date=timezone.now(),
                #         store_id=self.store_id
                #     )
        else:
            logger.warn(f'!!!model not found: {self.model_name}')

    def add_references(self):
        model_class = model_registry.get_model(self.model_name)
        if model_class:
            try:
                obj = model_class.objects.get(id=self.model_id)
                related_instance = obj.sharing_related_instances() # here we want instances granted by the DataAccess, including SYNC_MODEL_CHILDREN_SHARING
                related_instance.append(obj)

                with transaction.atomic():
                    for instance in related_instance:
                        logger.info(f'adds DataAccess to {instance.__class__.__name__}')
                        if isinstance(instance, BaseModel):
                            instance.add_data_access_relation(self)
                            instance.save()
            except ObjectDoesNotExist:
                pass

    def cleanup_references(self):
        model_class = model_registry.get_model(self.model_name)
        if model_class:
            try:
                obj = model_class.objects.get(id=self.model_id)
                related_instance = obj.related_instances()
                related_instance.append(obj)

                with transaction.atomic():
                    for instance in related_instance:
                        if isinstance(instance, BaseModel):
                            instance.remove_data_access_relation(self)
                            instance.save()
            except ObjectDoesNotExist:
                pass
