import os
from io import BytesIO
from pathlib import Path

from django.core.files.base import ContentFile
from django.core.management.base import BaseCommand
from django.db.models import Count
from PIL import Image

from market.models import MarketProduct, MarketProductImage


class Command(BaseCommand):
    help = (
        "Add a fallback image to all products that don't have any images. "
        "Uses farm_produce.jfif from the static/img directory."
    )

    def add_arguments(self, parser):
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Show which products would get the fallback image without making changes.",
        )

    def handle(self, *args, **options):
        # Find the fallback image
        fallback_image_path = self._find_fallback_image()
        if not fallback_image_path:
            self.stdout.write(
                self.style.ERROR(
                    "Fallback image 'farm_produce.jfif' or 'farm_produce.jpg' not found in static/img directory."
                )
            )
            return

        self.stdout.write(
            f"Using fallback image: {fallback_image_path}"
        )

        # Read and convert the image file
        try:
            with open(fallback_image_path, "rb") as f:
                fallback_image_content = self._convert_image_to_jpg(f.read(), Path(fallback_image_path).suffix)
        except Exception as exc:
            self.stdout.write(
                self.style.ERROR(f"Failed to read/convert fallback image: {exc}")
            )
            return

        # Find products without images
        products_without_images = (
            MarketProduct.objects.annotate(image_count=Count("images"))
            .filter(image_count=0)
            .order_by("category__name", "name")
        )
        count = products_without_images.count()

        self.stdout.write(
            self.style.WARNING(
                f"Found {count} product(s) without images. "
                f"Will add fallback image..."
            )
        )

        if options["dry_run"]:
            for product in products_without_images:
                self.stdout.write(f"  [DRY-RUN] {product.name} (id={product.id})")
            return

        # Add fallback image to products without images
        added_count = 0
        for product in products_without_images:
            try:
                # Create unique filename per product using JPG
                filename = f"fallback-{product.id}-farm_produce.jpg"
                upload = ContentFile(
                    fallback_image_content,
                    name=filename,
                )
                MarketProductImage.objects.create(
                    product=product,
                    image=upload,
                    alt_text=(product.name or "Product")[:255],
                    caption="Default marketplace image",
                    is_primary=True,
                    sort_order=0,
                )
                self.stdout.write(f"✓ {product.name} (id={product.id})")
                added_count += 1
            except Exception as exc:
                self.stdout.write(
                    self.style.ERROR(
                        f"✗ {product.name} (id={product.id}): {exc}"
                    )
                )

        self.stdout.write("")
        self.stdout.write(
            self.style.SUCCESS(
                f"Fallback image successfully added to {added_count} product(s)."
            )
        )

    def _find_fallback_image(self):
        """Find the fallback image in static/img directory."""
        # Try multiple possible locations - prefer JPG over JFIF
        possible_paths = [
            # JPG version (preferred)
            Path(__file__).resolve().parent.parent.parent.parent / "static" / "img" / "farm_produce.jpg",
            # JFIF version (fallback)
            Path(__file__).resolve().parent.parent.parent.parent / "static" / "img" / "farm_produce.jfif",
            # Django STATIC_ROOT on Ubuntu
            Path("/home/dnjwfooe/boma-contract-backend/static/img/farm_produce.jpg"),
            Path("/home/dnjwfooe/boma-contract-backend/static/img/farm_produce.jfif"),
            # Generic production paths
            Path("/app/boma-contract-backend/static/img/farm_produce.jpg"),
            Path("/app/boma-contract-backend/static/img/farm_produce.jfif"),
            Path("/var/www/boma-contract-backend/static/img/farm_produce.jpg"),
            Path("/var/www/boma-contract-backend/static/img/farm_produce.jfif"),
            # Current working directory relative
            Path("static/img/farm_produce.jpg"),
            Path("static/img/farm_produce.jfif"),
            Path("./static/img/farm_produce.jpg"),
            Path("./static/img/farm_produce.jfif"),
        ]

        for path in possible_paths:
            if path.exists():
                format_type = "JPG" if path.name.endswith(".jpg") else "JFIF"
                self.stdout.write(self.style.SUCCESS(f"Found fallback image ({format_type}) at: {path}"))
                return str(path)

        # Print what we looked for to help debugging
        self.stdout.write(self.style.WARNING("Fallback image not found in these locations:"))
        for path in possible_paths:
            self.stdout.write(f"  - {path}")
        
        return None

    def _convert_image_to_jpg(self, image_bytes, original_extension):
        """Convert any image format to JPG for maximum compatibility."""
        try:
            # Open the image from bytes
            img = Image.open(BytesIO(image_bytes))
            
            # Convert CMYK or other modes to RGB
            if img.mode in ("CMYK", "LA", "P"):
                rgb_img = Image.new("RGB", img.size, (255, 255, 255))
                rgb_img.paste(img)
                img = rgb_img
            elif img.mode == "RGBA":
                rgb_img = Image.new("RGB", img.size, (255, 255, 255))
                rgb_img.paste(img, mask=img.split()[3])
                img = rgb_img
            elif img.mode != "RGB":
                img = img.convert("RGB")
            
            # Save to JPG in memory
            buffer = BytesIO()
            img.save(buffer, format="JPEG", quality=95, optimize=True)
            buffer.seek(0)
            
            self.stdout.write(self.style.SUCCESS(f"✓ Converted {original_extension} to JPG format"))
            return buffer.read()
        except Exception as exc:
            self.stdout.write(self.style.WARNING(f"Could not convert image: {exc}. Using original format."))
            return image_bytes
