import datetime
import mimetypes
import os
import typing

from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator, URLValidator
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.urls import reverse
from django.utils.safestring import mark_safe
from markdownx.models import MarkdownxField

from shared.models import NameStrMixin
from users.models import User


class SubdomainValidatedURLField(models.URLField):
    validators = [
        URLValidator(schemes=("https",)),
        RegexValidator(regex=r"https:\/\/.*\.pirati.cz(\/|$).*"),
    ]


class OwnPermissionsMixin(models.Model):
    class Meta:
        abstract = True

        permissions = [
            ("edit_others", "Upravit cizí"),
            ("delete_others", "Odstranit cizí"),
        ]


class ContractCountMixin(models.Model):
    def get_contract_count(self, user) -> None:
        filter = {"is_approved": True}

        if not user.has_perm("contract.view_confidential"):
            filter["is_public"] = True

        return self.contracts.filter(**filter).count()

    class Meta:
        abstract = True


class SignatureCountMixin(models.Model):
    def get_signature_count(self, user) -> None:
        filter = {"contract__is_approved": True}

        if not user.has_perm("contract.view_confidential"):
            filter["contract__is_approved"] = True

        return self.signatures.filter(**filter).count()

    class Meta:
        abstract = True


class InlineNameMixin(models.Model):
    @property
    def inline_name(self) -> str:
        result = self.name

        if self.department:
            result += f", {self.department}"

        return result

    class Meta:
        abstract = True


class CreatedByMixin(models.Model):
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name="+",
        verbose_name="Vytvořeno uživatelem",
    )  # WARNING: exclude in admin

    class Meta:
        abstract = True


class RepresentativeMixin:
    @property
    def name(self):
        raise NotImplementedError

    @property
    def function(self):
        raise NotImplementedError

    def __str__(self) -> str:
        result = self.name

        if self.function is not None:
            result += f", {self.function}"

        return result


def get_default_country():
    return settings.DEFAULT_COUNTRY


class Signee(
    CreatedByMixin,
    OwnPermissionsMixin,
    SignatureCountMixin,
    InlineNameMixin,
    models.Model,
):
    name = models.CharField(
        max_length=256,
        verbose_name="Jméno",
    )

    class EntityTypes(models.TextChoices):
        NATURAL_PERSON = "natural_person", "Fyzická osoba"
        LEGAL_ENTITY = "legal_entity", "Právnická osoba"
        BUSINESS_NATURAL_PERSON = "business_natural_person", "Podnikající fyzická osoba"
        OTHER = "other", "Jiné"

    entity_type = models.CharField(
        max_length=23,
        choices=EntityTypes.choices,
        default=EntityTypes.LEGAL_ENTITY,
        verbose_name="Typ",
        help_text="Důležité označit správně! Fyzickým osobám nepublikujeme adresu.",
    )

    address_street_with_number = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Ulice, č.p.",
        help_text="Veřejné pouze, když typ není nastaven na fyzickou osobu.",
    )  # WARNING: Legal entity status dependent!

    address_district = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Obec",
    )

    address_zip = models.CharField(
        max_length=16,
        blank=True,
        null=True,
        verbose_name="PSČ",
        help_text="Veřejné pouze, když typ není nastaven na fyzickou osobu.",
    )  # WARNING: Legal entity status dependent!

    address_country = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Země",
        default=get_default_country,
    )

    ico_number = models.CharField(
        max_length=16,
        blank=True,
        null=True,
        verbose_name="IČO",
        help_text=(
            "U právnických a podnikajících fyzických osob musí být vyplněno. "
            "Vyplněním můžeš automaticky načíst data z ARES."
        ),
    )  # WARNING: Legal entity status dependent!

    date_of_birth = models.DateField(
        blank=True,
        null=True,
        verbose_name="Datum narození",
        help_text="U fyzických osob musí být vyplněno.",
    )  # WARNING: Legal entity status dependent!

    department = models.CharField(
        max_length=128,
        blank=True,
        null=True,
        verbose_name="Organizační složka",
    )

    @property
    def url(self) -> str:
        return reverse("contracts:view_signee", args=(self.id,))

    @property
    def entity_has_public_address(self) -> bool:
        return self.entity_type in (
            self.EntityTypes.LEGAL_ENTITY,
            self.EntityTypes.OTHER,
        )

    @property
    def has_any_address_information(self) -> bool:
        for field in (
            "address_street_with_number",
            "address_district",
            "address_zip",
            "address_country",
        ):
            if getattr(self, field):
                return True

        return False

    def clean(self):
        if (
            self.entity_type == self.EntityTypes.NATURAL_PERSON
            and not self.date_of_birth
        ):
            raise ValidationError(
                {"date_of_birth": "U fyzických osob musí být definováno."}
            )

        if (
            self.entity_type
            in (self.EntityTypes.LEGAL_ENTITY, self.EntityTypes.BUSINESS_NATURAL_PERSON)
            and not self.ico_number
        ):
            raise ValidationError(
                {
                    "ico_number": "U právnických a podnikajících fyzických osob musí být definováno."
                }
            )

        if self.entity_type != self.EntityTypes.OTHER:
            for field in (
                "address_street_with_number",
                "address_district",
                "address_zip",
                "address_country",
            ):
                if not getattr(self, field):
                    raise ValidationError(
                        {field: 'Pokud není vybrán typ "Jiné", musí být definováno.'}
                    )

        return super().clean()

    def __str__(self) -> str:
        result = self.name

        if self.ico_number is not None:
            result += f" ({self.ico_number})"

        if self.date_of_birth is not None:
            result += f" ({self.date_of_birth})"

        if self.department is not None:
            result += f", {self.department}"

        return result

    class Meta:
        app_label = "contracts"

        verbose_name = "Jiná smluvní strana"
        verbose_name_plural = "Ostatní smluvní strany"

        permissions = OwnPermissionsMixin.Meta.permissions


def get_default_contractee_name() -> str:
    return settings.DEFAULT_CONTRACTEE_NAME


def get_default_contractee_street() -> str:
    return settings.DEFAULT_CONTRACTEE_STREET


def get_default_contractee_district() -> str:
    return settings.DEFAULT_CONTRACTEE_DISTRICT


def get_default_contractee_zip() -> str:
    return settings.DEFAULT_CONTRACTEE_ZIP


def get_default_contractee_ico_number() -> str:
    return settings.DEFAULT_CONTRACTEE_ICO_NUMBER


class Contractee(
    CreatedByMixin,
    OwnPermissionsMixin,
    SignatureCountMixin,
    InlineNameMixin,
    models.Model,
):
    name = models.CharField(
        max_length=256,
        default=get_default_contractee_name,
        verbose_name="Jméno",
    )

    address_street_with_number = models.CharField(
        max_length=256,
        default=get_default_contractee_street,
        verbose_name="Ulice, č.p.",
    )

    address_district = models.CharField(
        max_length=256,
        default=get_default_contractee_district,
        verbose_name="Obec",
    )

    address_zip = models.CharField(
        max_length=16,
        default=get_default_contractee_zip,
        verbose_name="PSČ",
    )

    address_country = models.CharField(
        max_length=256,
        verbose_name="Země",
        default=get_default_country,
    )

    ico_number = models.CharField(
        max_length=16,
        blank=True,
        null=True,
        default=get_default_contractee_ico_number,
        verbose_name="IČO",
    )

    department = models.CharField(
        max_length=128,
        blank=True,
        null=True,
        verbose_name="Organizační složka",
    )

    @property
    def url(self) -> str:
        return reverse("contracts:view_contractee", args=(self.id,))

    def __str__(self) -> str:
        result = self.name

        if self.department is not None:
            result += f", {self.department}"

        return result

    class Meta:
        app_label = "contracts"

        verbose_name = "Naše smluvní strana"
        verbose_name_plural = "Naše smluvní strany"

        permissions = OwnPermissionsMixin.Meta.permissions


class ContractType(ContractCountMixin, NameStrMixin, models.Model):
    name = models.CharField(
        max_length=32,
        verbose_name="Jméno",
    )

    @property
    def url(self) -> str:
        return reverse("contracts:view_contract_type", args=(self.id,))

    class Meta:
        app_label = "contracts"

        verbose_name = "Typ smlouvy"
        verbose_name_plural = "Typy smluv"


class ContractIssue(ContractCountMixin, NameStrMixin, models.Model):
    name = models.CharField(
        max_length=32,
        verbose_name="Jméno",
    )

    @property
    def url(self) -> str:
        return reverse("contracts:view_contract_issue", args=(self.id,))

    class Meta:
        app_label = "contracts"

        verbose_name = "Problém se smlouvou"
        verbose_name_plural = "Problémy se smlouvami"


class ContractFilingArea(ContractCountMixin, NameStrMixin, models.Model):
    name = models.CharField(
        max_length=32,
        verbose_name="Jméno",
    )

    person_responsible = models.CharField(
        max_length=256,
        verbose_name="Odpovědná osoba",
    )

    @property
    def url(self) -> str:
        return reverse("contracts:view_contract_filing_area", args=(self.id,))

    class Meta:
        app_label = "contracts"

        verbose_name = "Spisovna"
        verbose_name_plural = "Spisovny"


def get_current_utc_timestamp():
    return datetime.datetime.now(datetime.timezone.utc)


# Pre-squash migration compatibility
get_created_on_timestamp = get_current_utc_timestamp


class Contract(NameStrMixin, models.Model):
    # BEGIN Automatically set fields

    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name="uploaded_contracts",
        verbose_name="Vytvořena uživatelem",
        help_text="Pokud vytváříš novou smlouvu, autorem budeš ty.",
    )  # WARNING: exclude in admin

    created_on = models.DateTimeField(
        blank=False,
        null=False,
        default=get_current_utc_timestamp,
        verbose_name="Čas vytvoření",
    )
    updated_on = models.DateTimeField(
        blank=False,
        null=False,
        default=get_current_utc_timestamp,
        verbose_name="Čas poslední aktualizace",
    )

    public_status_set_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name="public_status_altered_contracts",
        verbose_name="Zveřejněno / nezveřejněno uživatelem",
        help_text="Obsah není veřejně přístupný.",
    )  # WARNING: exclude in admin

    all_parties_sign_date = models.DateField(
        verbose_name="Datum podpisu všech stran",
        blank=True,
        null=True,
    )  # WARNING: Exclude in admin, autofill

    # END Automatically set fields

    # BEGIN Approval fields

    is_approved = models.BooleanField(
        verbose_name="Je schválená",
        default=False,
        help_text=(
            "Mohou měnit jen schvalovatelé. Pokud je "
            "smlouva veřejná, schválením se vypustí ven."
        ),
    )

    # END Approval fields

    name = models.CharField(
        max_length=128,
        verbose_name="Název",
    )

    id_number = models.CharField(
        max_length=128,
        blank=True,
        null=True,
        verbose_name="Identifikační číslo",
    )

    types = models.ManyToManyField(
        ContractType,
        related_name="contracts",
        verbose_name="Typ",
    )

    summary = models.TextField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Sumarizace obsahu smlouvy",
    )

    valid_start_date = models.DateField(
        blank=True,
        null=True,
        verbose_name="Začátek účinnosti",
        help_text=mark_safe(
            "<strong>Pokud není začátek účinnosti zadán, vypočítá se automaticky "
            "podle posledního data podpisu.</strong>"
        ),
    )
    valid_end_date = models.DateField(
        blank=True,
        null=True,
        verbose_name="Konec účinnosti",
        help_text=mark_safe(
            "<strong>Pokud není konec účinnosti zadán, smlouva je evidována jako "
            "na dobu neurčitou.</strong>"
        ),
    )

    class LegalStates(models.TextChoices):
        VALID = "valid", "Platná"
        INVALID = "invalid", "Neplatná"

    class PublicStates(models.TextChoices):
        YES = "yes", "Veřejná"
        NO = "no", "Neveřejná"

    class PaperFormStates(models.TextChoices):
        ON_THE_WAY = "on_the_way", "Na cestě"
        SENT = "sent", "Odeslaný"
        MAILBOX = "mailbox", "Ve schránce"

        TO_SHRED = "to_shred", "Ke skartaci"
        SHREDDED = "shredded", "Skartovaný"

        STORED = "stored", "Uložený"

        LOST = "lost", "Ztracený"

    legal_state = models.CharField(
        max_length=13,
        choices=LegalStates.choices,
        verbose_name="Stav právního ujednání",
    )

    is_public = models.BooleanField(
        default=True,
        verbose_name="Je veřejná",
        help_text=(
            "Neveřejné smlouvy nejsou vidět bez přihlášení jako min. tajný čtenář."
        ),
    )
    publishing_rejection_comment = models.TextField(
        max_length=65536,
        blank=True,
        null=True,
        verbose_name="Důvod nezveřejnění",
        help_text="Obsah není veřejně přístupný.",
    )  # WARNING: public status dependent

    paper_form_state = models.CharField(
        max_length=10,
        choices=PaperFormStates.choices,
        verbose_name="Stav fyzického dokumentu",
    )

    tender_url = SubdomainValidatedURLField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Odkaz na výběrové řízení",
        help_text=mark_safe(
            'Běžně odkaz na <a href="https://forum.pirati.cz/viewforum.php?f=572">VŘ sekci</a> '
            "fóra. Musí začínat <i>https</i> a být pod doménou <i>pirati.cz</i>."
        ),
    )

    agreement_url = SubdomainValidatedURLField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Odkaz na schválení",
        help_text=mark_safe(
            "Běžně odkaz na fórum. Využívá se např. u koaličních smluv. "
            "Musí začínat <i>https</i> a být pod doménou <i>pirati.cz</i>."
        ),
    )  # WARNING: Dependent on the type!

    issues = models.ManyToManyField(
        ContractIssue,
        blank=True,
        related_name="contracts",
        verbose_name="Problémy",
        help_text='Veřejně nazváno "Poznámky".',
    )

    class CostUnits(models.TextChoices):
        HOUR = "hour", "Hodina"
        MONTH = "month", "Měsíc"
        YEAR = "year", "Rok"
        TOTAL = "total", "Celkem"
        OTHER = "other", "Jiné"

    cost_amount = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name="Náklady (Kč)",
        help_text="Pokud se smlouvu nejsou spojené náklady, nevyplňuj vůbec.",
    )

    cost_unit = models.CharField(
        max_length=5,
        choices=CostUnits.choices,
        blank=True,
        null=True,
        verbose_name="Jednotka nákladů",
    )

    cost_unit_other = models.CharField(
        max_length=128,
        verbose_name="Jednotka nákladů (jiné)",
        help_text='Je nutno vyplnit v případě, že máš vybranou možnost "jiné" v jednotce nákladů.',
        blank=True,
        null=True,
    )

    filing_area = models.ForeignKey(
        ContractFilingArea,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name="contracts",
        verbose_name="Spisovna",
        help_text="Obsah není veřejně přístupný.",
    )

    primary_contract = models.ForeignKey(
        "Contract",
        on_delete=models.SET_NULL,  # TODO: Figure out if we want this behavior
        blank=True,
        null=True,
        related_name="subcontracts",
        verbose_name="Primární smlouva",
        help_text="Např. pro dodatky nebo objednávky u rámcových smluv.",
    )  # WARNING: Dependent on the type!

    notes = MarkdownxField(
        blank=True,
        null=True,
        verbose_name="Poznámky",
        help_text="Poznámky jsou viditelné pro všechny, kteří mohou smlouvu spravovat a pro tajné čtenáře.",
    )

    @property
    def primary_contract_url(self) -> typing.Union[None, str]:
        if self.primary_contract is None:
            return

        return reverse(
            "contracts:view_contract",
            args=(self.primary_contract.id,),
        )

    @property
    def url(self) -> str:
        return reverse(
            "contracts:view_contract",
            args=(self.id,),
        )

    def get_public_files(self):
        return ContractFile.objects.filter(
            contract=self,
            is_public=True,
        ).all()

    def get_private_files(self):
        return ContractFile.objects.filter(
            contract=self,
            is_public=False,
        ).all()

    def calculate_signing_parties_sign_date(self) -> None:
        contractees_latest_sign_date = None
        signees_latest_sign_date = None

        for contractee_signature in self.contractee_signatures.all():
            if (
                contractees_latest_sign_date is None
                or contractee_signature.date > contractees_latest_sign_date
            ):
                contractees_latest_sign_date = contractee_signature.date

        for signee_signature in self.signee_signatures.all():
            if (
                signees_latest_sign_date is None
                or signee_signature.date > signees_latest_sign_date
            ):
                signees_latest_sign_date = signee_signature.date

        if (
            contractees_latest_sign_date is not None
            and signees_latest_sign_date is not None
        ):
            self.all_parties_sign_date = max(
                (contractees_latest_sign_date, signees_latest_sign_date)
            )

        self.save()

    def clean(self):
        if not self.is_public and not self.publishing_rejection_comment:
            raise ValidationError(
                {
                    "publishing_rejection_comment": "Pokud smlouva není veřejná, toto pole musí být vyplněné."
                }
            )
        elif self.is_public and self.publishing_rejection_comment:
            raise ValidationError(
                {
                    "publishing_rejection_comment": "Nemůže být definováno, pokud je smlouva veřejná."
                }
            )

        if (
            self.valid_start_date
            and self.valid_end_date
            and self.valid_start_date > self.valid_end_date
        ):
            raise ValidationError(
                {
                    "valid_end_date": "Konec platnosti nemůže být definován dříve, než začátek."
                }
            )

        if self.cost_amount is None and self.cost_unit:  # 0 is falsy, but a value
            raise ValidationError(
                {"cost_unit": "Nemůže být definováno, pokud nejsou zadány náklady."}
            )

        if (
            self.cost_amount is not None  # 0 is falsy, but a value
            and not self.cost_unit
        ):
            raise ValidationError(
                {"cost_amount": "Nemůže být definováno bez jednoty nákladů."}
            )

        if self.cost_unit == self.CostUnits.OTHER and not self.cost_unit_other:
            raise ValidationError(
                {
                    "cost_unit_other": 'Musí být definováno, pokud je vybrána jednotka nákladů "jiné".'
                }
            )
        elif self.cost_unit != self.CostUnits.OTHER and self.cost_unit_other:
            raise ValidationError(
                {
                    "cost_unit_other": 'Nemůže být definováno, pokud není vybrána jednotka nákladů "jiné".'
                }
            )

        if (
            self.primary_contract is not None
            and self.is_public
            and not self.primary_contract.is_public
        ):
            raise ValidationError(
                {
                    "is_public": "Primární smlouva je neveřejná, tato smlouva nemůže být veřejná."
                }
            )

        return super().clean()

    def save(self, *args, **kwargs):
        self.updated_on = get_current_utc_timestamp()

        return super().save(*args, **kwargs)

    class Meta:
        app_label = "contracts"

        verbose_name = "Smlouva"
        verbose_name_plural = "Smlouvy"

        permissions = [
            ("approve", "Schválit / zrušit schválení"),
            ("view_confidential", "Zobrazit tajné informace"),
            ("edit_when_approved", "Upravit schválené"),
            ("delete_when_approved", "Odstranit schválené"),
        ] + OwnPermissionsMixin.Meta.permissions


def get_contract_file_loaction(instance, filename):
    mimetypes_instance = mimetypes.MimeTypes()

    current_time = datetime.datetime.today()
    guessed_type = mimetypes_instance.guess_type(filename, strict=False)[0]

    extension = ""

    if guessed_type is not None:
        for mapper in mimetypes_instance.types_map_inv:
            if guessed_type not in mapper:
                continue

            extension = mapper[guessed_type]
            break

    return (
        "_private/"
        f"{current_time.year}/{current_time.month}/{current_time.day}/"
        f"{str(instance.id)}{extension}"
    )


class ContractFile(NameStrMixin, models.Model):
    name = models.CharField(
        max_length=128,
        blank=True,
        null=True,
        verbose_name="Jméno",
    )

    is_public = models.BooleanField(
        verbose_name="Veřejně dostupný",
    )

    file = models.FileField(
        verbose_name="Soubor",
        upload_to=get_contract_file_loaction,
    )

    contract = models.ForeignKey(
        Contract,
        on_delete=models.CASCADE,
        related_name="files",
        verbose_name="Soubory",
    )

    @property
    def protected_url(self) -> str:
        return reverse(
            "contracts:download_contract_file",
            args=(self.id,),
        )

    class Meta:
        app_label = "contracts"

        verbose_name = "Soubor"
        verbose_name_plural = "Soubory"


class ContracteeSignature(models.Model):
    contractee = models.ForeignKey(
        Contractee,
        on_delete=models.CASCADE,
        related_name="signatures",
        verbose_name="Smluvní strana",
    )

    contract = models.ForeignKey(
        Contract,
        on_delete=models.CASCADE,
        related_name="contractee_signatures",
        verbose_name="Podpisy našich smluvních stran",
    )

    date = models.DateField(
        verbose_name="Datum podpisu",
    )

    role = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Role",
        help_text='Např. "nájemník"',
    )

    def __str__(self) -> str:
        return f"{str(self.contractee)} - {self.date}"

    class Meta:
        app_label = "contracts"

        verbose_name = "Podpis naší smluvní strany"
        verbose_name_plural = "Podpisy našich smluvních stran"


class SigneeSignature(models.Model):
    signee = models.ForeignKey(
        Signee,
        on_delete=models.CASCADE,
        related_name="signatures",
        verbose_name="Smluvní strana",
    )

    contract = models.ForeignKey(
        Contract,
        on_delete=models.CASCADE,
        related_name="signee_signatures",
        verbose_name="Podpisy jiných smluvních stran",
    )

    date = models.DateField(
        verbose_name="Datum podpisu",
    )

    role = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Role",
        help_text='Např. "pronajímatel"',
    )

    def __str__(self) -> str:
        return f"{str(self.signee)} - {self.date}"

    class Meta:
        app_label = "contracts"

        verbose_name = "Podpis jiné smluvní strany"
        verbose_name_plural = "Podpisy jiných smluvních stran"


class ContracteeSignatureRepresentative(RepresentativeMixin, models.Model):
    contractee_signature = models.ForeignKey(
        ContracteeSignature,
        on_delete=models.CASCADE,
        related_name="representatives",
        verbose_name="Podpis naši smluvní strany",
    )

    name = models.CharField(
        max_length=256,
        verbose_name="Jméno",
    )

    function = models.CharField(
        max_length=256,
        verbose_name="Funkce",
    )

    class Meta:
        app_label = "contracts"

        verbose_name = "Zástupce naší smluvní strany"
        verbose_name_plural = "Zástupci naší smluvní strany"


class SigneeSignatureRepresentative(RepresentativeMixin, models.Model):
    signee_signature = models.ForeignKey(
        SigneeSignature,
        on_delete=models.CASCADE,
        related_name="representatives",
        verbose_name="Podpis jiné smluvní strany",
    )

    name = models.CharField(
        max_length=256,
        verbose_name="Jméno",
    )

    function = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Funkce",
    )

    class Meta:
        app_label = "contracts"

        verbose_name = "Zástupce jiné smluvní strany"
        verbose_name_plural = "Zástupci jiné smluvní strany"


@receiver(post_save, sender=ContracteeSignature)
@receiver(post_save, sender=SigneeSignature)
def signing_parties_post_save_update_dates(sender, instance, *args, **kwargs) -> None:
    instance.contract.calculate_signing_parties_sign_date()


class ContractIntent(NameStrMixin, models.Model):
    name = models.CharField(
        max_length=128,
        verbose_name="Jméno",
    )

    url = SubdomainValidatedURLField(
        max_length=256,
        verbose_name="Odkaz",
        help_text=mark_safe(
            "Musí začínat <i>https</i> a být pod doménou <i>pirati.cz</i>."
        ),
    )

    contract = models.ForeignKey(
        Contract,
        on_delete=models.CASCADE,
        related_name="intents",
        verbose_name="Smlouva",
    )

    class Meta:
        app_label = "contracts"

        verbose_name = "Záměr v Piroplácení"
        verbose_name_plural = "Záměry v Piroplácení"