import click
from django.conf import settings
from django.core.cache import cache
from django.core.files.storage import default_storage
from versatileimagefield import settings as vif_settings
from versatileimagefield.image_warmer import VersatileImageFieldWarmer

from funkwhale_api.common import utils as common_utils
from funkwhale_api.common.models import Attachment

from . import base


@base.cli.group()
def media():
    """Manage media files (avatars, covers, attachments…)"""
    pass


@media.command("generate-thumbnails")
@click.option("-d", "--delete", is_flag=True)
def generate_thumbnails(delete):
    """
    Generate thumbnails for all images (avatars, covers, etc.).

    This can take a long time and generate a lot of I/O depending of the size
    of your library.
    """
    click.echo("Deleting existing thumbnails…")
    if delete:
        try:
            # FileSystemStorage doesn't support deleting a non-empty directory
            # so we reimplemented a method to do so
            default_storage.force_delete("__sized__")
        except AttributeError:
            # backends doesn't support directory deletion
            pass
    MODELS = [
        (Attachment, "file", "attachment_square"),
    ]
    for model, attribute, key_set in MODELS:
        click.echo(f"Generating thumbnails for {model._meta.label}.{attribute}…")
        qs = model.objects.exclude(**{f"{attribute}__isnull": True})
        qs = qs.exclude(**{attribute: ""})
        cache_key = "*{}{}*".format(
            settings.MEDIA_URL, vif_settings.VERSATILEIMAGEFIELD_SIZED_DIRNAME
        )
        entries = cache.keys(cache_key)
        if entries:
            click.echo(f"  Clearing {len(entries)} cache entries: {cache_key}…")
            for keys in common_utils.batch(iter(entries)):
                cache.delete_many(keys)
        warmer = VersatileImageFieldWarmer(
            instance_or_queryset=qs,
            rendition_key_set=key_set,
            image_attr=attribute,
            verbose=True,
        )
        click.echo("  Creating images")
        num_created, failed_to_create = warmer.warm()
        click.echo(f"  {num_created} created, {len(failed_to_create)} in error")
