"""
PPM Domain — Scoring & Prioritization Entities

موجودیت‌های دامنه امتیازدهی و اولویت‌بندی پروژه.
"""

from dataclasses import dataclass, field
from datetime import datetime
from decimal import Decimal
from typing import Optional
from uuid import UUID

from shared.base_classes.entity import TenantEntity
from ..value_objects.common import ScoringCriterionCategory


@dataclass
class ScoringModel(TenantEntity):
    """
    مدل امتیازدهی — مجموعه‌ای از معیارها برای ارزیابی و اولویت‌بندی پروژه‌ها.

    Business Rules:
    - هر مدل باید نامی یکتا (per tenant) داشته باشد
    - فقط یک مدل می‌تواند فعال باشد per portfolio
    - مجموع وزن معیارها باید ۱۰۰ باشد
    """
    name: str = ""
    description: str = ""
    portfolio_id: Optional[UUID] = None
    is_active: bool = True
    metadata: dict = field(default_factory=dict)

    def activate(self) -> None:
        self.is_active = True

    def deactivate(self) -> None:
        self.is_active = False


@dataclass
class ScoringCriterion(TenantEntity):
    """
    معیار امتیازدهی — یک بُعد ارزیابی با وزن مشخص.

    Business Rules:
    - weight باید عدد مثبت باشد (وزن نسبی)
    - scale_min < scale_max
    - category باید از ScoringCriterionCategory باشد
    """
    scoring_model_id: UUID = None
    name: str = ""
    description: str = ""
    weight: Decimal = Decimal("0")
    scale_min: int = 1
    scale_max: int = 10
    category: str = ScoringCriterionCategory.STRATEGIC.value
    order: int = 0

    def validate_score(self, score: int) -> bool:
        """بررسی اینکه امتیاز در بازه مجاز است."""
        return self.scale_min <= score <= self.scale_max


@dataclass
class ProjectScore(TenantEntity):
    """
    امتیاز پروژه — امتیاز یک پروژه بر اساس یک معیار خاص.

    Business Rules:
    - score باید بین scale_min و scale_max معیار باشد
    - هر پروژه فقط یک امتیاز per criterion
    """
    scoring_model_id: UUID = None
    project_id: UUID = None
    criterion_id: UUID = None
    score: Decimal = Decimal("0")
    justification: str = ""
    scored_by_id: Optional[UUID] = None
    scored_at: Optional[datetime] = None

    def update_score(self, new_score: Decimal, justification: str = "") -> None:
        self.score = new_score
        if justification:
            self.justification = justification
        self.scored_at = datetime.now()
