from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from .models import Projects, ProductFocus
from products.models import FeaturedProducts, Products
import logging
from utils.r2.client import R2
from django.contrib.contenttypes.models import ContentType

LOGGER = logging.getLogger(__name__)


@receiver(pre_delete, sender=Projects)
def delete_project_images_in_cloudflare(sender, instance, **kwargs):
    instance: Projects = instance
    project_images = getattr(instance, "images", None)

    product_focuses = ProductFocus.objects.filter(project__id=instance.id)

    r2 = R2()

    if project_images:
        r2.delete_objects(r2_path_list=project_images)
        LOGGER.info(f"Deleted project images in Cloudflare: {instance.title}")

    if product_focuses:
        images_to_delete = []

        for focus in product_focuses:
            image = focus.product_image_path
            images_to_delete.append(image)

        if images_to_delete:
            r2.delete_objects(r2_path_list=images_to_delete)
            LOGGER.info(f"Deleted product focus image in Cloudflare.")

        product_focuses.delete()
        LOGGER.info(f"Deleted product focuses.")


@receiver(post_save, sender=Projects)
def create_featured_products_and_product_focuses(sender, instance, created, **kwargs):
    featured_products: list[Products] = getattr(instance, "_featured_products", None)
    product_focuses: list[dict] = getattr(instance, "_product_focuses", None)

    if product_focuses:
        LOGGER.info(f"Creating product focuses for project: {instance.title}")

        existing_project_product_focuses = ProductFocus.objects.filter(
            project__id=instance.id
        )
        existing_project_product_focuses_id = list(
            str(uuid)
            for uuid in existing_project_product_focuses.values_list("id", flat=True)
        )

        retained_product_focuses_ids = []
        product_focuses_to_create = []

        for pf in product_focuses:
            id = pf.get("id", None)
            product_image = pf.get("product_image", None)
            collection = pf.get("collection")
            product_name = pf.get("product_name")
            product_description = pf.get("product_description")

            if id is not None:
                """
                During the update, store the retained product focus ids in a list and it will be compared with the
                current product focus ids of the project to check if there were removed
                product focuses or none.
                """
                product_focus = existing_project_product_focuses.get(id=id)

                if product_image is not None:
                    r2 = R2(file=product_image, main_folder_name="projects")
                    pf_r2_path = r2.upload_fileobj(
                        sub_folder_path=f"{instance.title}/product_focus/"
                    )
                    product_focus.product_image_path = pf_r2_path

                product_focus.collection = collection
                product_focus.product_name = product_name
                product_focus.product_description = product_description
                product_focus.save()

                retained_product_focuses_ids.append(id)
            else:
                """
                If no id is provided, then the product focus is a new object assigned
                to the project.
                """
                r2 = R2(file=product_image, main_folder_name="projects")
                pf_r2_path = r2.upload_fileobj(
                    sub_folder_path=f"{instance.title}/product_focus/"
                )

                product_focuses_to_create.append(
                    ProductFocus(
                        project=instance,
                        product_image_path=pf_r2_path,
                        collection=collection,
                        product_name=product_name,
                        product_description=product_description,
                    )
                )

        if product_focuses_to_create:
            ProductFocus.objects.bulk_create(product_focuses_to_create)
            LOGGER.info(f"Created new product focuses for project {instance.title}")

        removed_product_focuses = list(
            set(existing_project_product_focuses_id) - set(retained_product_focuses_ids)
        )

        if removed_product_focuses:
            ProductFocus.objects.filter(
                id__in=removed_product_focuses,
            ).delete()
            LOGGER.info(
                f"Removed product focuses deleted from project {instance.title}"
            )

    if featured_products:
        LOGGER.info(f"Creating featured products for project: {instance.title}")
        new_featured_products_list = []

        projects_content_type = ContentType.objects.get_for_model(Projects)

        existing_project_featured_products = FeaturedProducts.objects.filter(
            model=projects_content_type, model_object_id=instance.id
        ).values_list("product__id", flat=True)

        new_featured_ids = {product.id for product in featured_products}
        removed_product_ids = list(
            set(existing_project_featured_products) - new_featured_ids
        )

        for product in featured_products:
            if product.id not in existing_project_featured_products:
                new_featured_products_list.append(
                    FeaturedProducts(
                        model=projects_content_type,
                        model_object_id=instance.id,
                        product=product,
                    )
                )

        if removed_product_ids:
            FeaturedProducts.objects.filter(
                model=projects_content_type,
                model_object_id=instance.id,
                product__id__in=removed_product_ids,
            ).delete()
            LOGGER.info(
                f"Deleted featured products removed from project {instance.title}"
            )

        LOGGER.info(f"Featured products added for project: {instance.title}")
        FeaturedProducts.objects.bulk_create(new_featured_products_list)
