from collections import defaultdict

from django import forms
from django.core.exceptions import ValidationError

from orchestra.contrib.webapps.models import WebApp

from .utils import normurlpath
from .validators import validate_domain_protocol, validate_server_name
from orchestra.settings import WEB_SERVERS

class WebsiteAdminForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(WebsiteAdminForm, self).__init__(*args, **kwargs)
        if self.instance.id is None:
            qsServer = self.fields['target_server'].queryset.filter(name__in=WEB_SERVERS)
        else:
            qsServer = self.fields['target_server'].queryset.filter(id=self.instance.target_server_id)
        self.fields['target_server'].queryset = qsServer

    def clean(self):
        """ Prevent multiples domains on the same protocol """
        super(WebsiteAdminForm, self).clean()
        domains = self.cleaned_data.get('domains')
        if not domains:
            return self.cleaned_data
        protocol = self.cleaned_data.get('protocol')
        domains = domains.all()
        for domain in domains:
            try:
                validate_domain_protocol(self.instance, domain, protocol)
            except ValidationError as err:
                self.add_error(None, err)
        try:
            validate_server_name(domains)
        except ValidationError as err:
            self.add_error('domains', err)
        return self.cleaned_data
    
    def clean_target_server(self):
        # valida que el webapp pertenezca al server indicado
        try:
            server = self.cleaned_data['target_server']
        except:
            server = self.instance.target_server

        diferentServer = False
        for i in range(int(self.data['content_set-TOTAL_FORMS']) + 1):
            if f"content_set-{i}-webapp" in self.data.keys() and f"content_set-{i}-DELETE" not in self.data.keys():
                if self.data[f"content_set-{i}-webapp"]:
                    idWebapp = self.data[f"content_set-{i}-webapp"]
                    webapp = WebApp.objects.get(id=idWebapp)
                    if webapp.target_server.id != server.id :
                        diferentServer = True
        if diferentServer:
            self.add_error("target_server", f"Some Webapp does not belong to the {server.name} server")
        return server


class WebsiteDirectiveInlineFormSet(forms.models.BaseInlineFormSet):
    def clean(self):
        # directives formset cross-validation with contents for unique locations
        locations = set()
        for form in self.content_formset.forms:
            location = form.cleaned_data.get('path')
            delete = form.cleaned_data.get('DELETE')
            if not delete and location is not None:
                locations.add(normurlpath(location))
        
        values = defaultdict(list)
        for form in self.forms:
            wdirective = form.instance
            directive = form.cleaned_data
            if directive.get('name') is not None:
                try:
                    wdirective.directive_instance.validate_uniqueness(directive, values, locations)
                except ValidationError as err:
                    for k,v in err.error_dict.items():
                        form.add_error(k, v)