"""
PPM Domain — Portfolio Entity

پرتفولیو — Aggregate Root ماژول مدیریت پرتفولیو.
"""

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 PortfolioStatus, ReviewCycle, RiskTolerance


@dataclass
class Portfolio(TenantEntity):
    """
    پرتفولیو — Aggregate Root.

    مجموعه‌ای از برنامه‌ها و پروژه‌ها که
    به صورت هماهنگ مدیریت می‌شوند.
    """

    # --- Identity ---
    code: str = ""
    name: str = ""
    description: str = ""

    # --- Hierarchy ---
    parent_id: Optional[UUID] = None  # Multi-portfolio hierarchy

    # --- Status ---
    status: PortfolioStatus = PortfolioStatus.DRAFT

    # --- Strategy ---
    strategic_alignment_score: Decimal = Decimal("0")
    risk_tolerance: RiskTolerance = RiskTolerance.MEDIUM

    # --- Financial ---
    total_budget: Decimal = Decimal("0")
    allocated_budget: Decimal = Decimal("0")

    # --- Timeline ---
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    review_cycle: ReviewCycle = ReviewCycle.QUARTERLY

    # --- Ownership ---
    owner_id: Optional[UUID] = None     # → User
    company_id: Optional[UUID] = None   # → Company (Platform)
    org_unit_id: Optional[UUID] = None  # → OrganizationalUnit (Platform)

    # --- 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 == PortfolioStatus.DRAFT and self.name != ""

    def can_close(self) -> bool:
        return self.status in (PortfolioStatus.ACTIVE, PortfolioStatus.ON_HOLD)

    def activate(self) -> None:
        if not self.can_activate():
            raise ValueError("پرتفولیو قابل فعال‌سازی نیست.")
        self.status = PortfolioStatus.ACTIVE

    def close(self) -> None:
        if not self.can_close():
            raise ValueError("پرتفولیو قابل بسته شدن نیست.")
        self.status = PortfolioStatus.CLOSED

    def hold(self) -> None:
        if self.status != PortfolioStatus.ACTIVE:
            raise ValueError("فقط پرتفولیوی فعال قابل توقف است.")
        self.status = PortfolioStatus.ON_HOLD

    def archive(self) -> None:
        if self.status != PortfolioStatus.CLOSED:
            raise ValueError("فقط پرتفولیوی بسته‌شده قابل آرشیو است.")
        self.status = PortfolioStatus.ARCHIVED

    @property
    def remaining_budget(self) -> Decimal:
        return self.total_budget - self.allocated_budget
