import uuid

from django.conf import settings
from django.db import models


class ClinicalRotationPlan(models.Model):
    """Immutable approval boundary for one clinical-rotation revision."""

    class Status(models.TextChoices):
        PREVIEW_PENDING = "preview_pending", "Preview pending"
        PREVIEW_READY = "preview_ready", "Preview ready"
        PREVIEW_INFEASIBLE = "preview_infeasible", "Preview infeasible"
        COMMIT_PENDING = "commit_pending", "Commit pending"
        SYNC_PENDING = "sync_pending", "Sync pending"
        COMMITTED = "committed", "Committed"
        STALE = "stale", "Stale"
        FAILED = "failed", "Failed"
        EXPIRED = "expired", "Expired"

    plan_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
    deployment_scope = models.CharField(max_length=190)
    session_id = models.CharField(max_length=255)
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT,
        related_name="clinical_rotation_plans",
    )
    preview_operation_id = models.UUIDField()
    academic_term = models.ForeignKey("api.TtAcademicTerm", on_delete=models.PROTECT)
    module = models.ForeignKey("api.TtModule", on_delete=models.PROTECT)
    status = models.CharField(
        max_length=32, choices=Status.choices, default=Status.PREVIEW_PENDING
    )
    revision = models.PositiveIntegerField(default=1)
    normalized_request = models.JSONField(default=dict)
    request_hash = models.CharField(max_length=71)
    effective_constraint_setting = models.JSONField(default=dict)
    constraint_breaking_mode = models.BooleanField(default=False)
    input_fingerprint = models.CharField(max_length=71)
    clinical_input_snapshot_id = models.CharField(max_length=190)
    snapshot_content_hash = models.CharField(max_length=71)
    clinical_input_snapshot = models.JSONField(default=dict)
    preview_request_id = models.UUIDField(null=True, blank=True)
    commit_request_id = models.UUIDField(null=True, blank=True)
    engine_preview_token = models.TextField(null=True, blank=True)
    engine_state_version = models.CharField(max_length=255, null=True, blank=True)
    preview_hash = models.CharField(max_length=71, null=True, blank=True)
    preview_result = models.JSONField(null=True, blank=True)
    commit_result = models.JSONField(null=True, blank=True)
    failure = models.JSONField(null=True, blank=True)
    expires_at = models.DateTimeField()
    confirmed_at = models.DateTimeField(null=True, blank=True)
    committed_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "clinical_rotation_plan"
        constraints = [
            models.UniqueConstraint(
                fields=["deployment_scope", "created_by", "preview_operation_id"],
                name="uq_cr_plan_preview_operation",
            ),
            models.CheckConstraint(
                condition=models.Q(constraint_breaking_mode=False),
                name="ck_cr_plan_breaking_false",
            ),
        ]
        indexes = [
            models.Index(fields=["status", "expires_at"], name="ix_cr_plan_status_exp"),
            models.Index(
                fields=["academic_term", "status"], name="ix_cr_plan_term_status"
            ),
        ]

    def __str__(self):
        return f"{self.plan_id}:r{self.revision}:{self.status}"
