"""
Strategy Domain — Objective Entity (OKR)

هدف راهبردی — هسته سیستم 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 ObjectiveLevel, ObjectiveTimeFrame, ObjectiveStatus


@dataclass
class Objective(TenantEntity):
    """
    هدف راهبردی (Objective).

    اهداف می‌توانند سلسله‌مراتبی باشند (parent ← child)
    و به تم راهبردی متصل شوند.
    """

    # --- Relations ---
    theme_id: Optional[UUID] = None   # → StrategicTheme
    parent_id: Optional[UUID] = None  # → Objective (self-ref)

    # --- Identity ---
    title: str = ""
    description: str = ""

    # --- Classification ---
    level: str = ObjectiveLevel.ENTERPRISE
    time_frame: str = ObjectiveTimeFrame.ANNUAL

    # --- Period ---
    period_start: Optional[date] = None
    period_end: Optional[date] = None

    # --- Status ---
    status: str = ObjectiveStatus.DRAFT

    # --- Progress ---
    weight: Decimal = Decimal("1.00")
    progress: Decimal = Decimal("0.00")  # 0-100 auto-calculated

    # --- Ownership ---
    owner_id: Optional[UUID] = None  # → User

    # --- Metadata ---
    tags: Optional[list] = field(default_factory=list)
    metadata: Optional[dict] = field(default_factory=dict)

    # ─── Business Rules ───

    def can_activate(self) -> bool:
        return (
            self.status == ObjectiveStatus.DRAFT
            and self.title != ""
            and self.period_start is not None
            and self.period_end is not None
        )

    def activate(self) -> None:
        if not self.can_activate():
            raise ValueError("هدف قابل فعال‌سازی نیست — عنوان و دوره الزامی است.")
        self.status = ObjectiveStatus.ACTIVE

    def mark_at_risk(self) -> None:
        if self.status != ObjectiveStatus.ACTIVE:
            raise ValueError("فقط هدف فعال قابل تغییر به در‌خطر است.")
        self.status = ObjectiveStatus.AT_RISK

    def achieve(self) -> None:
        if self.status not in (ObjectiveStatus.ACTIVE, ObjectiveStatus.AT_RISK):
            raise ValueError("فقط هدف فعال یا در‌خطر قابل تکمیل است.")
        self.status = ObjectiveStatus.ACHIEVED

    def miss(self) -> None:
        if self.status not in (ObjectiveStatus.ACTIVE, ObjectiveStatus.AT_RISK):
            raise ValueError("فقط هدف فعال یا در‌خطر قابل عدم‌تحقق است.")
        self.status = ObjectiveStatus.MISSED

    def update_progress(self, progress: Decimal) -> None:
        """بروزرسانی درصد پیشرفت (محاسبه توسط OKRCalculator)."""
        self.progress = min(max(progress, Decimal("0")), Decimal("100"))

    def validate_period(self) -> bool:
        if self.period_start and self.period_end:
            return self.period_end > self.period_start
        return True
