import logging
import os

from django.core.management.base import BaseCommand
from django.db import models, transaction

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = "Enrich TV series metadata from TMDB/OMDB APIs"

    def add_arguments(self, parser):
        parser.add_argument(
            "--force",
            action="store_true",
            help="Overwrite existing cover image",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Show what would be done without making changes",
        )
        parser.add_argument(
            "--imdb-id",
            type=str,
            help="Only process series with this imdb_id",
        )
        parser.add_argument(
            "--needs-metadata",
            action="store_true",
            help="Only process series missing imdb_id or with broken cover image",
        )

    def _has_broken_image(self, series) -> bool:
        """Check if a series has a cover_image set but the file is missing."""
        if not series.cover_image:
            return False
        try:
            return not os.path.exists(series.cover_image.path)
        except Exception:
            return True

    def handle(self, *args, **options):
        from videos.models import Series

        force = options["force"]
        dry_run = options["dry_run"]
        imdb_id = options["imdb_id"]
        needs_metadata = options["needs_metadata"]

        qs = Series.objects.all()
        if imdb_id:
            qs = qs.filter(imdb_id=imdb_id)
        if needs_metadata:
            qs = qs.filter(
                models.Q(imdb_id__isnull=True)
                | models.Q(imdb_id="")
                | models.Q(cover_image__isnull=True)
                | models.Q(cover_image="")
            )

        total = qs.count()
        self.stdout.write(f"Processing {total} series from DB filter")

        # Also find series with broken cover images
        broken_image_series = []
        if needs_metadata:
            broken_qs = Series.objects.filter(
                cover_image__isnull=False,
            ).exclude(
                models.Q(imdb_id__isnull=True)
                | models.Q(imdb_id="")
                | models.Q(cover_image__isnull=True)
                | models.Q(cover_image=""),
            )
            if imdb_id:
                broken_qs = broken_qs.filter(imdb_id=imdb_id)
            for series in broken_qs.iterator():
                if self._has_broken_image(series):
                    broken_image_series.append(series)

        all_series = list(qs) + broken_image_series
        total = len(all_series)
        self.stdout.write(f"Total series to process: {total}")

        if dry_run:
            for series in all_series:
                has_imdb = bool(series.imdb_id)
                has_image = bool(series.cover_image)
                image_broken = self._has_broken_image(series)
                status = f"imdb_id={'✓' if has_imdb else '✗'}"
                if image_broken:
                    status += ", image=BROKEN"
                elif has_image:
                    status += ", image=✓"
                else:
                    status += ", image=✗"
                self.stdout.write(f"  [DRY RUN] Would fix {series.name} ({status})")
            return

        updated = 0
        errors = 0
        for series in all_series:
            try:
                with transaction.atomic():
                    series.fix_metadata(force_update=force or self._has_broken_image(series))
                updated += 1
                self.stdout.write(f"  [{updated}/{total}] {series.name}")
            except Exception as e:
                errors += 1
                self.stdout.write(
                    self.style.ERROR(
                        f"  Error updating series {series.name} (imdb_id={series.imdb_id}): {e}"
                    )
                )

        self.stdout.write(
            self.style.SUCCESS(f"\nDone! {updated} series updated, {errors} errors")
        )
