import functools
from urllib.parse import urlencode, urljoin

from django import http, forms
from django.conf import settings
from django.contrib import admin
from django.core import validators
from django.forms.models import modelformset_factory
from django.http.response import (
    HttpResponseForbidden,
    HttpResponseNotAllowed,
    HttpResponseRedirect,
)
from django.shortcuts import get_object_or_404
from django.urls import re_path, resolve, reverse
from django.utils.encoding import force_str
from django.utils.html import format_html, format_html_join
from django.utils.translation import gettext, gettext_lazy as _

import olympia.core.logger
from olympia import amo
from olympia.access import acl
from olympia.activity.models import ActivityLog
from olympia.addons.models import Addon, AddonUser
from olympia.amo.utils import send_mail
from olympia.files.models import File
from olympia.git.models import GitExtractionEntry
from olympia.ratings.models import Rating
from olympia.versions.models import Version
from olympia.zadmin.admin import related_content_link

from . import models
from .forms import AdminBaseFileFormSet, FileStatusForm


log = olympia.core.logger.getLogger('z.addons.admin')


class AddonUserInline(admin.TabularInline):
    model = AddonUser
    raw_id_fields = ('user',)
    readonly_fields = ('user_profile_link',)
    extra = 0

    def user_profile_link(self, obj):
        if obj.pk:
            return format_html(
                '<a href="{}">Admin User Profile</a> ({})',
                reverse('admin:users_userprofile_change', args=(obj.user.pk,)),
                obj.user.email,
            )
        else:
            return ''

    user_profile_link.short_description = 'User Profile'


class FileInlineChecks(admin.checks.InlineModelAdminChecks):
    def _check_relation(self, obj, parent_model):
        """File doesn't have a direct FK to Addon (it's via Version) so we have
        to bypass this check.
        """
        return []


class FileInline(admin.TabularInline):
    model = File
    extra = 0
    max_num = 0
    fields = (
        'created',
        'version__version',
        'version__channel',
        'status',
        'version__is_blocked',
        'hash_link',
    )
    editable_fields = ('status',)
    readonly_fields = tuple(set(fields) - set(editable_fields))
    can_delete = False
    view_on_site = False
    template = 'admin/addons/file_inline.html'
    checks_class = FileInlineChecks

    def version__version(self, obj):
        return obj.version.version + (' - Deleted' if obj.version.deleted else '')

    version__version.short_description = 'Version'

    def version__channel(self, obj):
        return obj.version.get_channel_display()

    version__channel.short_description = 'Channel'

    def version__is_blocked(self, obj):
        block = self.instance.block
        if not (block and block.is_version_blocked(obj.version.version)):
            return ''
        url = block.get_admin_url_path()
        template = '<a href="{}">Blocked ({} - {})</a>'
        return format_html(template, url, block.min_version, block.max_version)

    version__is_blocked.short_description = 'Block status'

    def hash_link(self, obj):
        url = reverse('zadmin.recalc_hash', args=(obj.id,))
        template = '<a href="{}" class="recalc" title="{}">Recalc Hash</a>'
        return format_html(template, url, obj.hash)

    hash_link.short_description = 'Hash'

    def get_formset(self, request, obj=None, **kwargs):
        self.instance = obj
        Formset = modelformset_factory(
            File,