from collections import defaultdict

from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404
from django.shortcuts import redirect
from django.urls import reverse

from localshop.views import index as base_index
from localshop.apps.packages.views import SimpleDetail as BaseSimpleDetail
from localshop.apps.packages.models import Repository, Release, ReleaseFile
from localshop.apps.packages.pypi import normalize_name


def index(request):
    if request.method == 'POST':
        return base_index(request)

    # Если у нас один репозиторий,
    # то с главной страницы редиректим на страницу этого репозитория
    try:
        repository = Repository.objects.get()
    except (Repository.DoesNotExist, Repository.MultipleObjectsReturned):
        return redirect('dashboard:index')
    else:
        return redirect('dashboard:repository_detail', repository.slug)


class SimpleDetail(BaseSimpleDetail):
    """
    https://st.yandex-team.ru/PYPI-170
    Переопределяем эту вьюху, потому что в localshop она неоптимальна (достает лишние данные)
    """
    def get(self, request, repo, slug):
        try:
            package = self.repository.packages.get(normalized_name=normalize_name(slug))
        except ObjectDoesNotExist:
            if not self.repository.enable_auto_mirroring:
                raise Http404("Auto mirroring is not enabled")

            # Пока не даем качать новые пакеты совсем PYPI-219
            raise Http404('Not found')
            # enqueue(fetch_package, self.repository.pk, slug)
            # return redirect(self.repository.upstream_pypi_url + '/' + slug)

        # Redirect if slug is not an exact match
        if slug != package.normalized_name:
            url = reverse('packages:simple_detail', kwargs={
                'repo': self.repository.slug,
                'slug': package.normalized_name
            })
            return redirect(url)

        self.object = package
        context = self.get_context_data(
            object=self.object,
            releases=self.get_releases(package),  # оптимизация тут
        )
        return self.render_to_response(context)

    def get_releases(self, package):
        releases = list(
            Release.objects
            .filter(package_id=package.id)
            .values('id', 'download_url', 'version')
        )
        release_files = list(
            ReleaseFile.objects
            .filter(release__package_id=package.id)
            .values(
                'id',
                'release_id',
                'requires_python',
                'filename',
                'md5_digest',
            )
        )

        release_files_mapping = defaultdict(list)
        for release_file in release_files:
            url = reverse(
                'packages:download',
                kwargs={
                    'repo': package.repository.slug,
                    'name': package.name,
                    'pk': release_file['id'],
                    'filename': release_file['filename'],
                }
            )
            release_file['get_absolute_url'] = '%s#md5=%s' % (url, release_file['md5_digest'])
            release_files_mapping[release_file['release_id']].append(release_file)

        for release in releases:
            release['files'] = {'all': release_files_mapping.get(release['id'], [])}

        return releases
