"""
PM Module — Cost & Budget Entities

هزینه، بودجه و مدیریت ارزش کسب‌شده (EVM).
"""

from dataclasses import dataclass, field
from datetime import date
from decimal import Decimal
from typing import Optional
from uuid import UUID, uuid4

from shared.base_classes.entity import TenantEntity

from ..value_objects.common import CostType


@dataclass
class Budget(TenantEntity):
    """
    بودجه پروژه — هر سطح WBS می‌تواند بودجه جداگانه داشته باشد.
    """

    project_id: UUID = field(default_factory=uuid4)
    task_id: Optional[UUID] = None    # بودجه در سطح WBS — null = سطح پروژه

    name: str = ""
    description: str = ""

    # --- Amounts ---
    original_budget: Decimal = Decimal("0")
    revised_budget: Decimal = Decimal("0")
    committed_cost: Decimal = Decimal("0")
    actual_cost: Decimal = Decimal("0")

    # --- Currency ---
    currency_id: Optional[UUID] = None    # → Currency (platform)

    # --- Period ---
    period_start: Optional[date] = None
    period_end: Optional[date] = None

    is_active: bool = True
    notes: str = ""

    @property
    def remaining_budget(self) -> Decimal:
        effective = self.revised_budget if self.revised_budget > 0 else self.original_budget
        return effective - self.actual_cost

    @property
    def budget_utilization(self) -> Optional[Decimal]:
        effective = self.revised_budget if self.revised_budget > 0 else self.original_budget
        if effective == 0:
            return None
        return (self.actual_cost / effective) * 100


@dataclass
class CostEntry(TenantEntity):
    """
    ثبت هزینه واقعی.
    """

    project_id: UUID = field(default_factory=uuid4)
    task_id: Optional[UUID] = None
    resource_id: Optional[UUID] = None
    budget_id: Optional[UUID] = None

    description: str = ""
    amount: Decimal = Decimal("0")
    cost_type: CostType = CostType.VARIABLE
    currency_id: Optional[UUID] = None    # → Currency (platform)

    entry_date: Optional[date] = None
    reference_number: str = ""

    # --- Metadata ---
    notes: str = ""
    metadata: Optional[dict] = field(default_factory=dict)
