"""
Strategy Domain — KeyResult Entity (OKR)

نتیجه کلیدی — معیار اندازه‌گیری تحقق هدف.
"""

from dataclasses import dataclass, field
from datetime import date
from decimal import Decimal
from typing import Optional
from uuid import UUID

from shared.base_classes.entity import TenantEntity

from ..value_objects.common import MetricType, ObjectiveStatus


@dataclass
class KeyResult(TenantEntity):
    """
    نتیجه کلیدی (Key Result).

    هر نتیجه کلیدی یک metric قابل اندازه‌گیری است
    که پیشرفت هدف را مشخص می‌کند.
    """

    # --- Relations ---
    objective_id: Optional[UUID] = None  # → Objective

    # --- Identity ---
    title: str = ""

    # --- Metric ---
    metric_type: str = MetricType.NUMBER
    start_value: Decimal = Decimal("0")
    target_value: Decimal = Decimal("100")
    current_value: Decimal = Decimal("0")

    # --- Weight & Status ---
    weight: Decimal = Decimal("1.00")
    status: str = ObjectiveStatus.DRAFT

    # --- Ownership ---
    owner_id: Optional[UUID] = None  # → User

    # --- Timeline ---
    due_date: Optional[date] = None

    # --- Metadata ---
    metadata: Optional[dict] = field(default_factory=dict)

    # ─── Business Rules ───

    @property
    def progress(self) -> Decimal:
        """محاسبه درصد پیشرفت بر اساس metric type."""
        if self.metric_type == MetricType.BOOLEAN:
            return Decimal("100") if self.current_value >= Decimal("1") else Decimal("0")

        denominator = self.target_value - self.start_value
        if denominator == 0:
            return Decimal("100") if self.current_value >= self.target_value else Decimal("0")

        raw = ((self.current_value - self.start_value) / denominator) * Decimal("100")
        return min(max(raw, Decimal("0")), Decimal("100"))

    def can_activate(self) -> bool:
        return self.status == ObjectiveStatus.DRAFT and self.title != ""

    def activate(self) -> None:
        if not self.can_activate():
            raise ValueError("نتیجه کلیدی قابل فعال‌سازی نیست.")
        self.status = ObjectiveStatus.ACTIVE

    def achieve(self) -> None:
        if self.status not in (ObjectiveStatus.ACTIVE, ObjectiveStatus.AT_RISK):
            raise ValueError("فقط نتیجه کلیدی فعال قابل تکمیل است.")
        self.status = ObjectiveStatus.ACHIEVED

    def update_value(self, value: Decimal) -> None:
        """بروزرسانی مقدار فعلی."""
        self.current_value = value
        # Auto-achieve if target reached
        if self.progress >= Decimal("100") and self.status == ObjectiveStatus.ACTIVE:
            self.status = ObjectiveStatus.ACHIEVED
