from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils import timezone

from flower.common import ModelBase


class MissionPayloadProcessorEnum(models.TextChoices):
    STRUCTURED_DESCRIPTION_V1 = "structured_description_v1", "结构化描述增强(v1)"


class MissionCategory(ModelBase):
    """任务分类字典，按商户隔离。"""

    id = models.BigAutoField(primary_key=True)
    merchant = models.ForeignKey(
        "basic_info.Merchant",
        on_delete=models.PROTECT,
        related_name="mission_categories",
        verbose_name="所属商户",
    )
    name = models.CharField(max_length=50, verbose_name="分类名称")
    payload_processor = models.CharField(
        max_length=50,
        blank=True,
        default="",
        choices=MissionPayloadProcessorEnum.choices,
        verbose_name="payload 增强器",
    )
    speech_enabled = models.BooleanField(default=False, verbose_name="是否播报")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "任务分类"
        verbose_name_plural = "任务分类"
        ordering = ["id"]
        constraints = [
            models.UniqueConstraint(fields=["merchant", "name"], name="unique_mission_category_name_per_merchant"),
        ]


class Mission(ModelBase):
    """中立任务，可选关联到系统中的任意业务对象。"""

    id = models.BigAutoField(primary_key=True)
    merchant = models.ForeignKey(
        "basic_info.Merchant",
        on_delete=models.PROTECT,
        related_name="missions",
        verbose_name="所属商户",
    )
    description = models.TextField(verbose_name="任务描述")
    category = models.ForeignKey(
        MissionCategory,
        on_delete=models.PROTECT,
        related_name="missions",
        verbose_name="任务类型",
    )
    is_urgent = models.BooleanField(default=False, db_index=True, verbose_name="是否紧急")
    is_completed = models.BooleanField(default=False, db_index=True, verbose_name="是否完成")
    is_cancelled = models.BooleanField(default=False, db_index=True, verbose_name="是否取消")
    notify_if_unreplied = models.BooleanField(default=False, db_index=True, verbose_name="是否开启未回复提醒")
    unreplied_notify_interval_minutes = models.PositiveIntegerField(
        null=True,
        blank=True,
        verbose_name="未回复提醒间隔（分钟）",
    )
    unreplied_notify_max_count = models.PositiveIntegerField(default=5, verbose_name="未回复最大提醒次数")
    unreplied_notify_sent_count = models.PositiveIntegerField(default=0, verbose_name="未回复已提醒次数")
    unreplied_last_notified_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="上一次未回复提醒时间",
    )
    cancelled_at = models.DateTimeField(null=True, blank=True, verbose_name="取消时间")
    creator = models.ForeignKey(
        "basic_info.Employee",
        on_delete=models.PROTECT,
        related_name="created_missions",
        verbose_name="任务创建者",
    )
    cancelled_by = models.ForeignKey(
        "basic_info.Employee",
        on_delete=models.PROTECT,
        related_name="cancelled_missions",
        null=True,
        blank=True,
        verbose_name="取消人",
    )
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.SET_NULL,
        related_name="missions",
        null=True,
        blank=True,
        verbose_name="关联对象类型",
    )
    content_id = models.PositiveBigIntegerField(null=True, blank=True, db_index=True, verbose_name="关联对象ID")
    extra = models.JSONField(null=True, blank=True, verbose_name="扩展字段")
    content_object = GenericForeignKey("content_type", "content_id")

    @property
    def has_ending_reply(self) -> bool:
        return self.replies.filter(ends_task=True, is_rejected=False).exists()

    @property
    def can_reply(self) -> bool:
        return not self.is_cancelled and not self.has_ending_reply

    @property
    def has_effective_reply(self) -> bool:
        return self.replies.filter(is_rejected=False).exists()

    def get_participants(self):
        return self.participants.select_related("employee")

    def filter_participants(self, **filters):
        return self.get_participants().filter(**filters)

    @property
    def category_name(self) -> str:
        return self.category.name

    def __str__(self):
        return f"Mission #{self.id}"

    class Meta:
        verbose_name = "任务"
        verbose_name_plural = "任务"
        permissions = [
            ("reopen_mission", "Can reopen mission"),
            ("reject_mission_reply", "Can reject mission reply"),
        ]
        indexes = [
            models.Index(fields=["merchant", "content_type", "content_id"]),
            models.Index(fields=["merchant", "is_completed", "is_cancelled"]),
        ]


class MissionParticipant(ModelBase):
    """任务参与员工。"""

    id = models.BigAutoField(primary_key=True)
    merchant = models.ForeignKey(
        "basic_info.Merchant",
        on_delete=models.PROTECT,
        related_name="mission_participants",
        verbose_name="所属商户",
    )
    mission = models.ForeignKey(
        Mission,
        on_delete=models.CASCADE,
        related_name="participants",
        verbose_name="任务",
    )
    employee = models.ForeignKey(
        "basic_info.Employee",
        on_delete=models.PROTECT,
        related_name="mission_participations",
        verbose_name="参与者",
    )

    def __str__(self):
        return f"{self.mission_id} - {self.employee_id}"

    class Meta:
        verbose_name = "任务参与者"
        verbose_name_plural = "任务参与者"
        constraints = [
            models.UniqueConstraint(fields=["mission", "employee"], name="unique_mission_participant"),
        ]


class MissionReply(ModelBase):
    """任务回应记录。"""

    id = models.BigAutoField(primary_key=True)
    merchant = models.ForeignKey(
        "basic_info.Merchant",
        on_delete=models.PROTECT,
        related_name="mission_replies",
        verbose_name="所属商户",
    )
    mission = models.ForeignKey(
        Mission,
        on_delete=models.CASCADE,
        related_name="replies",
        verbose_name="任务",
    )
    responder = models.ForeignKey(
        "basic_info.Employee",
        on_delete=models.PROTECT,
        related_name="mission_replies",
        verbose_name="回应者",
    )
    content = models.TextField(verbose_name="回应内容")
    extra = models.JSONField(null=True, blank=True, verbose_name="扩展字段")
    replied_at = models.DateTimeField(default=timezone.now, db_index=True, verbose_name="回应时间")
    ends_task = models.BooleanField(default=False, db_index=True, verbose_name="是否结束任务")
    is_rejected = models.BooleanField(default=False, db_index=True, verbose_name="是否被撤销")
    rejected_by = models.ForeignKey(
        "basic_info.Employee",
        on_delete=models.PROTECT,
        related_name="rejected_mission_replies",
        null=True,
        blank=True,
        verbose_name="撤销人",
    )
    rejected_at = models.DateTimeField(null=True, blank=True, verbose_name="撤销时间")

    def __str__(self):
        return f"MissionReply #{self.id}"

    class Meta:
        verbose_name = "任务回应"
        verbose_name_plural = "任务回应"
        ordering = ["replied_at", "id"]
