import copy

from django.contrib import admin
from django.utils.html import format_html
from fieldsets_with_inlines import FieldsetsInlineMixin
from import_export import resources
from nested_admin import NestedModelAdmin, NestedStackedInline, NestedTabularInline
from rangefilter.filters import DateRangeFilter

from shared.admin import MarkdownxGuardedModelAdmin

from .forms import ContractAdminForm, ContractFileAdminForm, SigneeAdminForm
from .models import (
    Contract,
    Contractee,
    ContracteeSignature,
    ContracteeSignatureRepresentative,
    ContractFile,
    ContractFilingArea,
    ContractIntent,
    ContractIssue,
    ContractType,
    Signee,
    SigneeSignature,
    SigneeSignatureRepresentative,
)


class ContractResource(resources.ModelResource):
    class Meta:
        model = Contract


class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
    def has_module_permission(self, request):
        return False


# BEGIN Contracts


class ContractFileAdmin(IndexHiddenModelAdmin):
    form = ContractFileAdminForm


class ContracteeSignatureRepresentativeInline(NestedStackedInline):
    model = ContracteeSignatureRepresentative
    extra = 0


class ContracteeSignatureInline(NestedStackedInline):
    model = ContracteeSignature
    autocomplete_fields = ("contractee",)
    inlines = (ContracteeSignatureRepresentativeInline,)
    extra = 0


class SigneeSignatureRepresentativeInline(NestedStackedInline):
    model = SigneeSignatureRepresentative
    extra = 0


class SigneeSignatureInline(NestedStackedInline):
    model = SigneeSignature
    autocomplete_fields = ("signee",)
    inlines = (SigneeSignatureRepresentativeInline,)
    extra = 0


class ContractFileInline(NestedTabularInline):
    model = ContractFile
    form = ContractFileAdminForm
    extra = 0


class ContractIntentInline(NestedTabularInline):
    model = ContractIntent
    extra = 0


class ContractAdmin(MarkdownxGuardedModelAdmin, FieldsetsInlineMixin, NestedModelAdmin):
    form = ContractAdminForm

    readonly_fields = ("created_by",)
    autocomplete_fields = (
        "types",
        "filing_area",
        "issues",
    )

    fieldsets_with_inlines = [
        (
            "Základní informace",
            {
                "fields": [
                    "name",
                    "id_number",
                    "types",
                    "summary",
                    "is_public",
                    "publishing_rejection_comment",
                    "legal_state",
                    "primary_contract",
                ]
            },
        ),
        (
            "Data",
            {
                "fields": [
                    "valid_start_date",
                    "valid_end_date",
                ]
            },
        ),
        (
            "Náklady",
            {
                "fields": [
                    "cost_amount",
                    "cost_unit",
                ]
            },
        ),
        ContractFileInline,
        ContracteeSignatureInline,
        SigneeSignatureInline,
        (
            "Odkazy",
            {
                "fields": [
                    "tender_url",
                    "agreement_url",
                ]
            },
        ),
        ContractIntentInline,
        (
            "Fyzický dokument",
            {
                "fields": [
                    "paper_form_state",
                    "filing_area",
                ]
            },
        ),
        (
            "Doplňující informace",
            {
                "fields": [
                    "issues",
                    "notes",
                ]
            },
        ),
    ]

    def get_fieldsets(self, request, obj=None):
        fieldsets_with_inlines = copy.deepcopy(self.fieldsets_with_inlines)

        if request.user.is_superuser or request.user.has_perm("approve", self):
            fieldsets_with_inlines.insert(
                8,
                ("Schválení", {"fields": ["is_approved"]}),
            )

        return [
            self.make_placeholder(index, fieldset)
            for index, fieldset in enumerate(fieldsets_with_inlines)
        ]

    def get_queryset(self, request):
        queryset = super().get_queryset(request)

        if not request.user.has_perm("contracts.view_confidential"):
            queryset = queryset.filter(is_public=True)

        if not request.user.has_perm("contracts.approve"):
            queryset = queryset.filter(is_approved=True)

        return queryset

    def save_model(self, request, obj, form, change) -> None:
        if obj.created_by is None:
            obj.created_by = request.user

        if obj.valid_start_date is None:
            last_signature_date = None

            for signature_set in (
                obj.contractee_signatures.all(),
                obj.signee_signatures.all(),
            ):
                for signature in signature_set:
                    if (
                        last_signature_date is None
                        or last_signature_date < signature.date
                    ):
                        last_signature_date = signature.date

            obj.valid_start_date = last_signature_date

        super().save_model(request, obj, form, change)

    list_filter = (
        "types",
        "is_approved",
        "legal_state",
        "is_public",
        "paper_form_state",
        "issues",
        ("all_parties_sign_date", DateRangeFilter),
        ("valid_start_date", DateRangeFilter),
        ("valid_end_date", DateRangeFilter),
    )

    list_display = (
        "name",
        "is_approved",
        "is_public",
    )


class ContractTypeAdmin(MarkdownxGuardedModelAdmin):
    model = ContractType
    ordering = ("name",)
    search_fields = ("name",)


class ContractIssueAdmin(MarkdownxGuardedModelAdmin):
    model = ContractIssue
    ordering = ("name",)
    search_fields = ("name",)


class ContractFilingAreaAdmin(MarkdownxGuardedModelAdmin):
    model = ContractFilingArea
    ordering = ("name",)
    search_fields = (
        "name",
        "person_responsible",
    )


# END Contracts

# BEGIN Signing parties


class ContracteeAdmin(MarkdownxGuardedModelAdmin):
    model = Contractee
    search_fields = (
        "name",
        "department",
        "role",
    )
    ordering = ("name",)


class SigneeAdmin(MarkdownxGuardedModelAdmin):
    model = Signee

    search_fields = (
        "name",
        "department",
        "role",
    )
    ordering = ("name",)

    form = SigneeAdminForm

    readonly_fields = ("load_ares_data_button",)

    list_filter = ("entity_type",)
    list_display = ("name", "entity_type")

    def get_fields(self, request, obj=None):
        fields = [
            "name",
            "entity_type",
            "ico_number",
            "department",
            "role",
        ]

        if (
            obj is None  # Creating
            or obj.entity_has_public_address
            or request.user.has_perm("contracts.view_confidential", obj)
        ):
            entity_type_index = fields.index("entity_type")

            fields[entity_type_index:entity_type_index] = [
                "address_street_with_number",
                "address_district",
                "address_zip",
                "address_country",
            ]

            fields.insert(
                fields.index("department") - 1,
                "date_of_birth",
            )

        if obj is None or request.user.has_perm(  # Allowed to create
            "contracts.edit_signee", obj
        ):
            fields.insert(fields.index("ico_number"), "load_ares_data_button")

        return fields

    def load_ares_data_button(self, obj):
        return format_html(
            '<button type="button" id="load_ares_data">Načíst data</button>'
        )

    load_ares_data_button.allow_tags = True
    load_ares_data_button.short_description = "ARES"


# END Signing parties


for model in (
    SigneeSignature,
    ContracteeSignature,
    ContracteeSignatureRepresentative,
    SigneeSignatureRepresentative,
    ContractIntent,
):
    admin.site.register(model, IndexHiddenModelAdmin)

admin.site.register(ContractType, ContractTypeAdmin)
admin.site.register(ContractIssue, ContractIssueAdmin)
admin.site.register(ContractFile, ContractFileAdmin)
admin.site.register(ContractFilingArea, ContractFilingAreaAdmin)

admin.site.register(Contractee, ContracteeAdmin)
admin.site.register(Signee, SigneeAdmin)

admin.site.register(Contract, ContractAdmin)