"""
PM Module — Domain Events

رویدادهای داخلی حوزه مدیریت پروژه.
"""

from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from typing import Optional
from uuid import UUID


@dataclass(frozen=True)
class PMDomainEvent:
    """رویداد پایه حوزه PM."""
    event_id: UUID
    tenant_id: UUID
    occurred_at: datetime
    version: int = 1


# ─── Project Events ──────────────────────────────────────────────────

@dataclass(frozen=True)
class ProjectCreated(PMDomainEvent):
    event_type: str = "pm.project.created"
    project_id: Optional[UUID] = None
    code: str = ""
    title: str = ""
    project_type: str = ""
    company_id: Optional[UUID] = None
    manager_id: Optional[UUID] = None


@dataclass(frozen=True)
class ProjectStatusChanged(PMDomainEvent):
    event_type: str = "pm.project.status_changed"
    project_id: Optional[UUID] = None
    old_status: str = ""
    new_status: str = ""


@dataclass(frozen=True)
class ProjectCompleted(PMDomainEvent):
    event_type: str = "pm.project.completed"
    project_id: Optional[UUID] = None
    actual_end: Optional[date] = None
    final_cost: Decimal = Decimal("0")


# ─── Task Events ─────────────────────────────────────────────────────

@dataclass(frozen=True)
class TaskCreated(PMDomainEvent):
    event_type: str = "pm.task.created"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    title: str = ""
    parent_id: Optional[UUID] = None


@dataclass(frozen=True)
class TaskCompleted(PMDomainEvent):
    event_type: str = "pm.task.completed"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    actual_end: Optional[date] = None


@dataclass(frozen=True)
class TaskAssigned(PMDomainEvent):
    event_type: str = "pm.task.assigned"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    assignee_id: Optional[UUID] = None


@dataclass(frozen=True)
class TaskStatusChanged(PMDomainEvent):
    """تغییر وضعیت تسک."""
    event_type: str = "pm.task.status_changed"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    old_status: str = ""
    new_status: str = ""


@dataclass(frozen=True)
class TaskProgressUpdated(PMDomainEvent):
    event_type: str = "pm.task.progress_updated"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    old_progress: int = 0
    new_progress: int = 0


# ─── Resource Events ─────────────────────────────────────────────────

@dataclass(frozen=True)
class ResourceAssigned(PMDomainEvent):
    event_type: str = "pm.resource.assigned"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    resource_id: Optional[UUID] = None
    units: Decimal = Decimal("100")


@dataclass(frozen=True)
class ResourceReleased(PMDomainEvent):
    event_type: str = "pm.resource.released"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    resource_id: Optional[UUID] = None


# ─── Cost Events ─────────────────────────────────────────────────────

@dataclass(frozen=True)
class CostRecorded(PMDomainEvent):
    event_type: str = "pm.cost.recorded"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    amount: Decimal = Decimal("0")
    cost_type: str = ""


# ─── Risk Events ─────────────────────────────────────────────────────

@dataclass(frozen=True)
class RiskIdentified(PMDomainEvent):
    event_type: str = "pm.risk.identified"
    project_id: Optional[UUID] = None
    risk_id: Optional[UUID] = None
    title: str = ""
    probability: str = ""
    impact: str = ""


@dataclass(frozen=True)
class RiskMitigated(PMDomainEvent):
    event_type: str = "pm.risk.mitigated"
    project_id: Optional[UUID] = None
    risk_id: Optional[UUID] = None


# ─── Baseline Events ─────────────────────────────────────────────────

@dataclass(frozen=True)
class BaselineCreated(PMDomainEvent):
    event_type: str = "pm.baseline.created"
    project_id: Optional[UUID] = None
    baseline_id: Optional[UUID] = None
    name: str = ""


# ─── Change Request Events ───────────────────────────────────────────

@dataclass(frozen=True)
class ChangeRequestSubmitted(PMDomainEvent):
    event_type: str = "pm.change_request.submitted"
    project_id: Optional[UUID] = None
    change_request_id: Optional[UUID] = None
    title: str = ""


@dataclass(frozen=True)
class ChangeRequestApproved(PMDomainEvent):
    event_type: str = "pm.change_request.approved"
    project_id: Optional[UUID] = None
    change_request_id: Optional[UUID] = None


@dataclass(frozen=True)
class ChangeRequestRejected(PMDomainEvent):
    event_type: str = "pm.change_request.rejected"
    project_id: Optional[UUID] = None
    change_request_id: Optional[UUID] = None


# ─── Milestone Events ────────────────────────────────────────────────

@dataclass(frozen=True)
class MilestoneReached(PMDomainEvent):
    event_type: str = "pm.milestone.reached"
    project_id: Optional[UUID] = None
    task_id: Optional[UUID] = None
    title: str = ""
    reached_date: Optional[date] = None


# ─── Timesheet Events ────────────────────────────────────────────────

@dataclass(frozen=True)
class TimesheetSubmitted(PMDomainEvent):
    event_type: str = "pm.timesheet.submitted"
    project_id: Optional[UUID] = None
    user_id: Optional[UUID] = None
    total_hours: Decimal = Decimal("0")


@dataclass(frozen=True)
class TimesheetApproved(PMDomainEvent):
    event_type: str = "pm.timesheet.approved"
    project_id: Optional[UUID] = None
    user_id: Optional[UUID] = None
    approved_by_id: Optional[UUID] = None


# ─── Issue Events ─────────────────────────────────────────────────────

@dataclass(frozen=True)
class IssueCreated(PMDomainEvent):
    event_type: str = "pm.issue.created"
    project_id: Optional[UUID] = None
    issue_id: Optional[UUID] = None
    title: str = ""
    severity: str = ""
    priority: str = ""


@dataclass(frozen=True)
class IssueAssigned(PMDomainEvent):
    event_type: str = "pm.issue.assigned"
    project_id: Optional[UUID] = None
    issue_id: Optional[UUID] = None
    assignee_id: Optional[UUID] = None


@dataclass(frozen=True)
class IssueResolved(PMDomainEvent):
    event_type: str = "pm.issue.resolved"
    project_id: Optional[UUID] = None
    issue_id: Optional[UUID] = None
    resolution: str = ""


@dataclass(frozen=True)
class IssueClosed(PMDomainEvent):
    event_type: str = "pm.issue.closed"
    project_id: Optional[UUID] = None
    issue_id: Optional[UUID] = None


# ─── OBS Events ──────────────────────────────────────────────────────

@dataclass(frozen=True)
class OBSNodeCreated(PMDomainEvent):
    event_type: str = "pm.obs_node.created"
    project_id: Optional[UUID] = None
    node_id: Optional[UUID] = None
    code: str = ""
    name: str = ""
    node_type: str = ""


@dataclass(frozen=True)
class OBSNodeUpdated(PMDomainEvent):
    event_type: str = "pm.obs_node.updated"
    project_id: Optional[UUID] = None
    node_id: Optional[UUID] = None
    name: str = ""


@dataclass(frozen=True)
class OBSNodeDeleted(PMDomainEvent):
    event_type: str = "pm.obs_node.deleted"
    project_id: Optional[UUID] = None
    node_id: Optional[UUID] = None
    code: str = ""


# ─── RBS Events ──────────────────────────────────────────────────────

@dataclass(frozen=True)
class RBSNodeCreated(PMDomainEvent):
    event_type: str = "pm.rbs_node.created"
    project_id: Optional[UUID] = None
    node_id: Optional[UUID] = None
    code: str = ""
    name: str = ""
    node_type: str = ""


@dataclass(frozen=True)
class RBSNodeUpdated(PMDomainEvent):
    event_type: str = "pm.rbs_node.updated"
    project_id: Optional[UUID] = None
    node_id: Optional[UUID] = None
    name: str = ""


@dataclass(frozen=True)
class RBSNodeDeleted(PMDomainEvent):
    event_type: str = "pm.rbs_node.deleted"
    project_id: Optional[UUID] = None
    node_id: Optional[UUID] = None
    code: str = ""


# ─── Quality Events ─────────────────────────────────────────────────

@dataclass(frozen=True)
class InspectionCompleted(PMDomainEvent):
    event_type: str = "pm.inspection.completed"
    project_id: Optional[UUID] = None
    inspection_id: Optional[UUID] = None
    code: str = ""
    result: str = ""


@dataclass(frozen=True)
class NCRCreated(PMDomainEvent):
    event_type: str = "pm.ncr.created"
    project_id: Optional[UUID] = None
    ncr_id: Optional[UUID] = None
    code: str = ""
    severity: str = ""


@dataclass(frozen=True)
class NCRResolved(PMDomainEvent):
    event_type: str = "pm.ncr.resolved"
    project_id: Optional[UUID] = None
    ncr_id: Optional[UUID] = None
    code: str = ""


# ═══════════════════════════════════════════════════
# Document Integration Events
# ═══════════════════════════════════════════════════

@dataclass(frozen=True)
class DocumentLinked(PMDomainEvent):
    event_type: str = "pm.document.linked"
    project_id: str = ""
    document_id: str = ""
    entity_type: str = ""
    entity_id: Optional[str] = None


@dataclass(frozen=True)
class DocumentUnlinked(PMDomainEvent):
    event_type: str = "pm.document.unlinked"
    project_id: str = ""
    document_id: str = ""
    entity_type: str = ""
    entity_id: Optional[str] = None
