from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import UniqueConstraint
from django.utils.translation import gettext_lazy as _

from members.models import Member
from rosterchief.base import ClubScopedModel, UUIDModel, unique_slugify


class Form(ClubScopedModel):
    title = models.CharField(_("title"), max_length=255)
    slug = models.SlugField(_("slug"), blank=True)
    description = models.TextField(_("description"), blank=True)

    slug_source = "title"

    is_active = models.BooleanField(_("is active?"), default=True)
    login_required = models.BooleanField(_("login required?"), default=False)

    opens_at = models.DateTimeField(_("opens at"), blank=True, null=True)
    closes_at = models.DateTimeField(_("closes at"), blank=True, null=True)
    max_submissions_per_user = models.PositiveIntegerField(_("max submissions per user"), blank=True, null=True)

    class Meta:
        verbose_name = _("form")
        verbose_name_plural = _("forms")
        ordering = ["title"]
        constraints = [
            UniqueConstraint(fields=["club", "slug"], name="unique_form_slug_per_club"),
        ]

    def __str__(self):
        return self.title


class Field(UUIDModel):
    class FieldType(models.TextChoices):
        TEXT = "text", _("text")
        TEXTAREA = "textarea", _("textarea")
        NUMBER = "number", _("number")
        EMAIL = "email", _("email")
        DATE = "date", _("date")
        CHOICE = "choice", _("choice")
        MULTICHOICE = "multichoice", _("multichoice")
        CHECKBOX = "checkbox", _("checkbox")
        FILE = "file", _("file")

    form = models.ForeignKey(Form, on_delete=models.CASCADE, related_name="fields", verbose_name=_("form"))
    key = models.SlugField(_("key"), blank=True)
    label = models.CharField(_("label"), max_length=255)
    field_type = models.CharField(_("field type"), max_length=255, choices=FieldType.choices, default=FieldType.TEXT)
    required = models.BooleanField(_("required?"), default=True)
    help_text = models.TextField(_("help text"), blank=True)
    order = models.PositiveIntegerField(_("order"), default=0)
    is_active = models.BooleanField(_("is active?"), default=True)
    options = models.JSONField(_("options"), blank=True, null=True)

    class Meta:
        verbose_name = _("field")
        verbose_name_plural = _("fields")
        ordering = ["form", "order"]
        constraints = [
            UniqueConstraint(fields=["form", "key"], name="unique_field_key_per_form"),
        ]

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = unique_slugify(self, self.label, slug_field="key", scope={"form": self.form})
        super().save(*args, **kwargs)

    def __str__(self):
        return self.label


class Submission(UUIDModel):
    form = models.ForeignKey(Form, on_delete=models.CASCADE, related_name="submissions", verbose_name=_("form"))
    member = models.ForeignKey(Member, on_delete=models.SET_NULL, related_name="submissions", verbose_name=_("member"), blank=True, null=True)
    submitted_at = models.DateTimeField(_("submitted at"), auto_now_add=True)

    class Meta:
        verbose_name = _("submission")
        verbose_name_plural = _("submissions")
        ordering = ["-submitted_at"]

    def __str__(self):
        return f"{self.form} - {self.member}"


class Answer(UUIDModel):
    submission = models.ForeignKey(Submission, on_delete=models.CASCADE, related_name="answers", verbose_name=_("submission"))
    field = models.ForeignKey(Field, on_delete=models.PROTECT, related_name="answers", verbose_name=_("field"))
    value = models.JSONField(_("value"), blank=True, null=True)

    class Meta:
        verbose_name = _("answer")
        verbose_name_plural = _("answers")
        ordering = ["submission", "field"]
        constraints = [
            UniqueConstraint(fields=["submission", "field"], name="unique_answer_per_field_per_submission"),
        ]

    def __str__(self):
        return f"{self.submission} - {self.field}"

    def clean(self):
        if self.field_id and self.submission_id and self.field.form_id != self.submission.form_id:
            raise ValidationError({"field": _("Must belong to the same form as the submission.")})
