"""BPM Process Maturity Assessment models — Phase 14.

Implements a 5-level maturity model (CMMI-inspired) for process assessment.

Model inventory
---------------
MaturityDimension          — TextChoices for assessment dimensions.
MaturityLevel              — Standard maturity level descriptor (1–5).
ProcessMaturityAssessment  — A scored assessment of a process.
MaturityImprovementAction  — An actionable improvement item from an assessment.

Design decisions
----------------
* ``MaturityLevel`` records are global reference data (no tenant FK).
  They should be pre-populated via a data migration or fixture.
* ``dimension_scores`` on ``ProcessMaturityAssessment`` is a JSONField
  that maps dimension keys (e.g. "documentation") to integer scores 1–5.
  This avoids a separate DimensionScore table while still supporting
  per-dimension radar charts.
* ``gap_to_target`` is a computed property (not stored).
* ``MaturityImprovementAction.status`` uses a simple TextChoices to
  avoid a full workflow integration at this phase.
"""

from __future__ import annotations

from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from simorgh.core.models import TimeStampedModel, UUIDModel
from simorgh.apps.bpm.models.process import ProcessDefinition


# ---------------------------------------------------------------------------
# Choices
# ---------------------------------------------------------------------------

class MaturityDimension(models.TextChoices):
    """Assessment dimensions used in dimension_scores."""
    DOCUMENTATION    = "documentation",    _("Documentation / مستندسازی")
    MEASUREMENT      = "measurement",      _("Measurement / اندازه‌گیری")
    STANDARDIZATION  = "standardization",  _("Standardization / استانداردسازی")
    AUTOMATION       = "automation",       _("Automation / خودکارسازی")
    CONTINUOUS_IMP   = "continuous_imp",   _("Continuous Improvement / بهبود مستمر")
    GOVERNANCE       = "governance",       _("Governance / حاکمیت")


class ActionStatus(models.TextChoices):
    OPEN        = "open",        _("Open / باز")
    IN_PROGRESS = "in_progress", _("In Progress / در جریان")
    DONE        = "done",        _("Done / انجام شده")
    CANCELLED   = "cancelled",   _("Cancelled / لغو شده")


# ---------------------------------------------------------------------------
# MaturityLevel — global reference data
# ---------------------------------------------------------------------------

class MaturityLevel(TimeStampedModel):
    """Standard 5-level maturity descriptor.

    Level 1 = Initial, 2 = Managed, 3 = Defined,
    4 = Quantitatively Managed, 5 = Optimizing.

    Pre-populated via fixture or data migration.
    """

    LEVEL_CHOICES = [(i, str(i)) for i in range(1, 6)]

    level = models.PositiveSmallIntegerField(
        _("level"),
        unique=True,
        choices=LEVEL_CHOICES,
    )
    name = models.CharField(_("name"), max_length=64)
    name_fa = models.CharField(_("name (FA)"), max_length=64, blank=True)
    description = models.TextField(_("description"), blank=True)
    description_fa = models.TextField(_("description (FA)"), blank=True)
    # Criteria per dimension: {"documentation": "...", "measurement": "..."}
    criteria = models.JSONField(_("criteria"), default=dict, blank=True)

    class Meta:
        verbose_name = _("maturity level")
        verbose_name_plural = _("maturity levels")
        ordering = ["level"]

    def __str__(self) -> str:
        return f"Level {self.level} — {self.name}"


# ---------------------------------------------------------------------------
# ProcessMaturityAssessment
# ---------------------------------------------------------------------------

class ProcessMaturityAssessment(TimeStampedModel, UUIDModel):
    """A scored maturity assessment for a process definition."""

    process = models.ForeignKey(
        ProcessDefinition,
        on_delete=models.CASCADE,
        related_name="maturity_assessments",
        verbose_name=_("process"),
    )
    assessed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name="bpm_maturity_assessments",
        verbose_name=_("assessed by"),
    )
    assessment_date = models.DateField(_("assessment date"))
    current_level = models.PositiveSmallIntegerField(
        _("current maturity level"),
        choices=MaturityLevel.LEVEL_CHOICES,
    )
    target_level = models.PositiveSmallIntegerField(
        _("target maturity level"),
        choices=MaturityLevel.LEVEL_CHOICES,
    )
    # {"documentation": 3, "measurement": 2, "standardization": 4, ...}
    dimension_scores = models.JSONField(
        _("dimension scores"),
        default=dict,
        blank=True,
        help_text=_("Map of dimension key → score (1–5)."),
    )
    improvement_notes = models.TextField(_("improvement notes"), blank=True)
    next_review_date = models.DateField(_("next review date"), null=True, blank=True)

    class Meta:
        verbose_name = _("process maturity assessment")
        verbose_name_plural = _("process maturity assessments")
        ordering = ["-assessment_date"]

    def __str__(self) -> str:
        return f"{self.process} — L{self.current_level} ({self.assessment_date})"

    @property
    def gap_to_target(self) -> int:
        """How many levels below the target."""
        return max(0, self.target_level - self.current_level)

    def average_dimension_score(self) -> float | None:
        """Mean of all dimension scores, or None if no scores recorded."""
        scores = [v for v in self.dimension_scores.values() if isinstance(v, (int, float))]
        if not scores:
            return None
        return round(sum(scores) / len(scores), 2)


# ---------------------------------------------------------------------------
# MaturityImprovementAction
# ---------------------------------------------------------------------------

class MaturityImprovementAction(TimeStampedModel, UUIDModel):
    """An actionable improvement item derived from a maturity assessment."""

    assessment = models.ForeignKey(
        ProcessMaturityAssessment,
        on_delete=models.CASCADE,
        related_name="improvement_actions",
        verbose_name=_("assessment"),
    )
    title = models.CharField(_("title"), max_length=256)
    description = models.TextField(_("description"), blank=True)
    target_level = models.PositiveSmallIntegerField(
        _("target level"),
        choices=MaturityLevel.LEVEL_CHOICES,
    )
    due_date = models.DateField(_("due date"), null=True, blank=True)
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="bpm_maturity_actions",
        verbose_name=_("owner"),
    )
    status = models.CharField(
        _("status"),
        max_length=16,
        choices=ActionStatus.choices,
        default=ActionStatus.OPEN,
        db_index=True,
    )

    class Meta:
        verbose_name = _("maturity improvement action")
        verbose_name_plural = _("maturity improvement actions")
        ordering = ["due_date", "status"]

    def __str__(self) -> str:
        return f"{self.title} ({self.assessment.process})"
