from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.urls import reverse
from generic.mixins import AuthorMixin

class Survey(models.Model, AuthorMixin):
    name = models.CharField(max_length=200, help_text="Title of the survey")
    description = models.TextField(blank=True, help_text="Introductory text or description")
    before_text = models.TextField(blank=True, help_text="Text shown to the user before they start the survey")
    after_text = models.TextField(blank=True, help_text="Text shown to the user after they complete the survey")
    created_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="created_surveys"
    )
    author = models.ManyToManyField(
        User,
        blank=True,
        related_name="surveys",
        help_text="Author/Manager(s) of the survey"
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    active = models.BooleanField(
        default=True,
        help_text="If inactive, users will not be able to fill out the survey."
    )
    anonymous = models.BooleanField(
        default=False,
        help_text="If checked, responses will not link to the user account or candidate details."
    )
    authors_only = models.BooleanField(
        default=False,
        help_text="If true, only survey authors will be able to view or manage this survey."
    )

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("survey:survey_detail", kwargs={"pk": self.pk})


class SurveyQuestion(models.Model):
    class QuestionType(models.TextChoices):
        TEXT = "TEXT", "Free Text"
        CHOICE = "CHOICE", "Multiple Choice (Single Option)"
        RATING = "RATING", "Rating (1-5 Likert scale)"
        INTEGER = "INTEGER", "Integer / Number"
        DATE = "DATE", "Date"

    survey = models.ForeignKey(
        Survey,
        on_delete=models.CASCADE,
        related_name="questions"
    )
    text = models.TextField(help_text="The question text to display to users")
    question_type = models.CharField(
        max_length=20,
        choices=QuestionType.choices,
        default=QuestionType.TEXT
    )
    choices = models.TextField(
        blank=True,
        help_text="For Multiple Choice questions, enter options separated by a new line."
    )
    required = models.BooleanField(
        default=True,
        help_text="If checked, users must answer this question to submit."
    )
    position = models.IntegerField(
        default=0,
        help_text="Ordering position of the question."
    )
    validation_rules = models.JSONField(
        default=dict,
        blank=True,
        null=True,
        help_text="Extensible validation rules in JSON format (e.g. min_value, max_value, min_date, max_date)"
    )

    class Meta:
        ordering = ["position", "id"]

    def __str__(self):
        return f"{self.survey.name} - Question {self.position}: {self.text[:50]}"

    def get_choices_list(self):
        if not self.choices:
            return []
        return [c.strip() for c in self.choices.split("\n") if c.strip()]


class SurveyResponse(models.Model):
    class SurveyContext(models.TextChoices):
        PRE = "PRE", "Pre-take survey"
        POST = "POST", "Post-take survey"
        GENERAL = "GENERAL", "General feedback"

    survey = models.ForeignKey(
        Survey,
        on_delete=models.CASCADE,
        related_name="responses"
    )
    user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="survey_responses"
    )
    cid = models.IntegerField(
        null=True,
        blank=True,
        help_text="Candidate ID if taken by an anonymous candidate login."
    )
    
    # Generic relationship to associate the response with a CaseCollection or Exam
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.SET_NULL,
        null=True,
        blank=True
    )
    object_id = models.PositiveIntegerField(null=True, blank=True)
    content_object = GenericForeignKey("content_type", "object_id")

    pre_or_post = models.CharField(
        max_length=10,
        choices=SurveyContext.choices,
        default=SurveyContext.GENERAL
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        user_str = self.user.username if self.user else (f"CID {self.cid}" if self.cid else "Anonymous")
        return f"Response for {self.survey.name} by {user_str} ({self.pre_or_post})"


class SurveyAnswer(models.Model):
    response = models.ForeignKey(
        SurveyResponse,
        on_delete=models.CASCADE,
        related_name="answers"
    )
    question = models.ForeignKey(
        SurveyQuestion,
        on_delete=models.CASCADE,
        related_name="answers"
    )
    text_answer = models.TextField(blank=True, null=True)
    choice_answer = models.CharField(max_length=255, blank=True, null=True)
    rating_answer = models.IntegerField(blank=True, null=True)
    integer_answer = models.IntegerField(blank=True, null=True)
    date_answer = models.DateField(blank=True, null=True)

    def __str__(self):
        return f"Answer to {self.question.id} for response {self.response.id}"
