"""
CLM Public Events - Module Contract.

رویدادهای عمومی ماژول مدیریت قراردادها که سایر ماژول‌ها می‌توانند subscribe کنند.
هیچ ماژول دیگری نباید مستقیم از domain events وارد کند.
"""
from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from typing import Optional
from uuid import UUID


# ═══════════════════════════════════════════════════
# Base
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class CLMEvent:
    """رویداد پایه ماژول CLM."""
    event_id: UUID
    tenant_id: UUID
    occurred_at: datetime
    version: int = 1


# ═══════════════════════════════════════════════════
# Contract Lifecycle Events
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class ContractCreated(CLMEvent):
    """قرارداد جدید ایجاد شد."""
    event_type: str = "clm.contract.created"
    contract_id: UUID = None
    contract_number: str = ""
    title: str = ""
    category: str = ""
    contract_type: str = ""
    total_value: Optional[Decimal] = None
    project_id: Optional[UUID] = None
    org_unit_id: Optional[UUID] = None


@dataclass(frozen=True)
class ContractApproved(CLMEvent):
    """قرارداد تأیید شد."""
    event_type: str = "clm.contract.approved"
    contract_id: UUID = None
    contract_number: str = ""
    approved_by: Optional[UUID] = None


@dataclass(frozen=True)
class ContractActivated(CLMEvent):
    """قرارداد فعال شد."""
    event_type: str = "clm.contract.activated"
    contract_id: UUID = None
    contract_number: str = ""
    start_date: Optional[date] = None
    end_date: Optional[date] = None
    total_value: Optional[Decimal] = None


@dataclass(frozen=True)
class ContractSuspended(CLMEvent):
    """قرارداد تعلیق شد."""
    event_type: str = "clm.contract.suspended"
    contract_id: UUID = None
    contract_number: str = ""
    reason: str = ""


@dataclass(frozen=True)
class ContractResumed(CLMEvent):
    """قرارداد ازسرگیری شد."""
    event_type: str = "clm.contract.resumed"
    contract_id: UUID = None
    contract_number: str = ""


@dataclass(frozen=True)
class ContractCompleted(CLMEvent):
    """قرارداد اتمام یافت."""
    event_type: str = "clm.contract.completed"
    contract_id: UUID = None
    contract_number: str = ""
    total_value: Optional[Decimal] = None


@dataclass(frozen=True)
class ContractTerminated(CLMEvent):
    """قرارداد فسخ شد."""
    event_type: str = "clm.contract.terminated"
    contract_id: UUID = None
    contract_number: str = ""
    reason: str = ""


@dataclass(frozen=True)
class ContractExpired(CLMEvent):
    """قرارداد منقضی شد."""
    event_type: str = "clm.contract.expired"
    contract_id: UUID = None
    contract_number: str = ""
    expiry_date: Optional[date] = None


@dataclass(frozen=True)
class ContractCancelled(CLMEvent):
    """قرارداد لغو شد."""
    event_type: str = "clm.contract.cancelled"
    contract_id: UUID = None
    contract_number: str = ""
    reason: str = ""


# ═══════════════════════════════════════════════════
# Amendment Events
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class ContractAmended(CLMEvent):
    """الحاقیه به قرارداد اعمال شد."""
    event_type: str = "clm.contract.amended"
    contract_id: UUID = None
    amendment_id: UUID = None
    amendment_type: str = ""
    old_total_value: Optional[Decimal] = None
    new_total_value: Optional[Decimal] = None
    old_end_date: Optional[date] = None
    new_end_date: Optional[date] = None


# ═══════════════════════════════════════════════════
# Renewal Events
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class ContractRenewed(CLMEvent):
    """قرارداد تمدید شد."""
    event_type: str = "clm.contract.renewed"
    contract_id: UUID = None
    renewal_number: int = 0
    old_end_date: Optional[date] = None
    new_end_date: Optional[date] = None
    old_value: Optional[Decimal] = None
    new_value: Optional[Decimal] = None


# ═══════════════════════════════════════════════════
# Milestone Events
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class MilestoneCompleted(CLMEvent):
    """مرحله قرارداد تکمیل شد."""
    event_type: str = "clm.milestone.completed"
    contract_id: UUID = None
    milestone_id: UUID = None
    milestone_type: str = ""
    amount: Optional[Decimal] = None


@dataclass(frozen=True)
class MilestoneOverdue(CLMEvent):
    """مرحله قرارداد عقب افتاد."""
    event_type: str = "clm.milestone.overdue"
    contract_id: UUID = None
    milestone_id: UUID = None
    due_date: Optional[date] = None
    delay_days: int = 0


# ═══════════════════════════════════════════════════
# Financial Events (for future FIN module)
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class ContractValueChanged(CLMEvent):
    """ارزش قرارداد تغییر کرد."""
    event_type: str = "clm.contract.value_changed"
    contract_id: UUID = None
    old_value: Optional[Decimal] = None
    new_value: Optional[Decimal] = None
    currency_id: Optional[UUID] = None
    reason: str = ""


@dataclass(frozen=True)
class ContractPaymentDue(CLMEvent):
    """پرداخت قرارداد موعد رسید."""
    event_type: str = "clm.contract.payment_due"
    contract_id: UUID = None
    milestone_id: UUID = None
    amount: Optional[Decimal] = None
    due_date: Optional[date] = None


# ═══════════════════════════════════════════════════
# Warning Events
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class ContractExpiryWarning(CLMEvent):
    """هشدار انقضای قرارداد."""
    event_type: str = "clm.contract.expiry_warning"
    contract_id: UUID = None
    contract_number: str = ""
    expiry_date: Optional[date] = None
    days_to_expiry: int = 0


@dataclass(frozen=True)
class GuaranteeExpiryWarning(CLMEvent):
    """هشدار انقضای ضمانت‌نامه."""
    event_type: str = "clm.guarantee.expiry_warning"
    contract_id: UUID = None
    guarantee_type: str = ""
    expiry_date: Optional[date] = None
    days_to_expiry: int = 0
