"""
PM Module — Baseline, Calendar, ChangeRequest, Timesheet, ProjectMember, Comment, ActivityLog

موجودیت‌های پشتیبانی ماژول مدیریت پروژه.
"""

from dataclasses import dataclass, field
from datetime import date, datetime, time
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 (
    BaselineType,
    ChangeRequestStatus,
    ChangeRequestPriority,
    TimesheetStatus,
    MemberRole,
)


# ─── Baseline ────────────────────────────────────────────────────────

@dataclass
class Baseline(TenantEntity):
    """
    خط پایه پروژه — Snapshot از زمان‌بندی و هزینه.
    """
    project_id: UUID = field(default_factory=uuid4)

    name: str = ""
    description: str = ""
    baseline_type: BaselineType = BaselineType.INITIAL
    is_active: bool = False

    # --- Snapshot ---
    snapshot_date: Optional[date] = None
    snapshot_data: Optional[dict] = field(default_factory=dict)  # JSON: tasks/dates/costs

    # --- Summary ---
    total_tasks: int = 0
    total_cost: Decimal = Decimal("0")
    planned_start: Optional[date] = None
    planned_end: Optional[date] = None

    def activate(self) -> None:
        self.is_active = True

    def deactivate(self) -> None:
        self.is_active = False


# ─── Calendar & Holiday ──────────────────────────────────────────────

@dataclass
class Calendar(TenantEntity):
    """
    تقویم کاری پروژه/منبع.
    """
    name: str = ""
    description: str = ""
    is_default: bool = False

    # --- Working hours ---
    work_start: time = time(8, 0)
    work_end: time = time(17, 0)
    hours_per_day: int = 8

    # --- Working days (0=Mon, 6=Sun) ---
    working_days: Optional[list] = field(default_factory=lambda: [0, 1, 2, 3, 5, 6])
    # Iran: شنبه تا پنجشنبه = [0=Mon→5=Sat] — ما از 0-6 استفاده می‌کنیم
    # working_days شامل جمعه (4=Friday) نیست

    metadata: Optional[dict] = field(default_factory=dict)


@dataclass
class Holiday(TenantEntity):
    """
    تعطیلات رسمی.
    """
    calendar_id: UUID = field(default_factory=uuid4)

    name: str = ""
    holiday_date: Optional[date] = None
    is_recurring: bool = False  # هر سال تکرار شود
    notes: str = ""


# ─── Change Request ──────────────────────────────────────────────────

@dataclass
class ChangeRequest(TenantEntity):
    """
    درخواست تغییر پروژه.
    یکپارچه‌سازی با Workflow Engine برای تأیید.
    """
    project_id: UUID = field(default_factory=uuid4)

    code: str = ""
    title: str = ""
    description: str = ""
    justification: str = ""

    status: ChangeRequestStatus = ChangeRequestStatus.DRAFT
    priority: ChangeRequestPriority = ChangeRequestPriority.MEDIUM

    # --- Impact ---
    scope_impact: str = ""
    cost_impact: Decimal = Decimal("0")
    schedule_impact_days: int = 0

    # --- Assignment ---
    requester_id: Optional[UUID] = None    # → User
    reviewer_id: Optional[UUID] = None     # → User

    # --- Workflow ---
    workflow_instance_id: Optional[UUID] = None  # → WorkflowProcessInstance

    # --- Dates ---
    submitted_date: Optional[date] = None
    decision_date: Optional[date] = None
    implementation_date: Optional[date] = None

    # --- Decision ---
    decision_notes: str = ""

    notes: str = ""
    metadata: Optional[dict] = field(default_factory=dict)

    def submit(self) -> None:
        if self.status != ChangeRequestStatus.DRAFT:
            raise ValueError("فقط درخواست‌های پیش‌نویس قابل ارسال هستند")
        self.status = ChangeRequestStatus.SUBMITTED
        self.submitted_date = date.today()

    def approve(self, notes: str = "") -> None:
        if self.status not in (ChangeRequestStatus.SUBMITTED, ChangeRequestStatus.UNDER_REVIEW):
            raise ValueError("درخواست در وضعیت قابل تأیید نیست")
        self.status = ChangeRequestStatus.APPROVED
        self.decision_date = date.today()
        self.decision_notes = notes

    def reject(self, notes: str = "") -> None:
        if self.status not in (ChangeRequestStatus.SUBMITTED, ChangeRequestStatus.UNDER_REVIEW):
            raise ValueError("درخواست در وضعیت قابل رد نیست")
        self.status = ChangeRequestStatus.REJECTED
        self.decision_date = date.today()
        self.decision_notes = notes


# ─── Timesheet ───────────────────────────────────────────────────────

@dataclass
class Timesheet(TenantEntity):
    """
    تایم‌شیت — ثبت ساعات کاری.
    """
    project_id: UUID = field(default_factory=uuid4)
    task_id: Optional[UUID] = None
    resource_id: Optional[UUID] = None
    user_id: Optional[UUID] = None           # → User

    work_date: Optional[date] = None
    regular_hours: Decimal = Decimal("0")
    overtime_hours: Decimal = Decimal("0")
    description: str = ""

    status: TimesheetStatus = TimesheetStatus.DRAFT
    approved_by_id: Optional[UUID] = None    # → User
    approved_date: Optional[date] = None

    notes: str = ""

    @property
    def total_hours(self) -> Decimal:
        return self.regular_hours + self.overtime_hours

    def submit(self) -> None:
        if self.status != TimesheetStatus.DRAFT:
            raise ValueError("فقط تایم‌شیت‌های پیش‌نویس قابل ارسال هستند")
        self.status = TimesheetStatus.SUBMITTED

    def approve(self, approver_id: UUID) -> None:
        if self.status != TimesheetStatus.SUBMITTED:
            raise ValueError("فقط تایم‌شیت‌های ارسال‌شده قابل تأیید هستند")
        self.status = TimesheetStatus.APPROVED
        self.approved_by_id = approver_id
        self.approved_date = date.today()

    def reject(self) -> None:
        if self.status != TimesheetStatus.SUBMITTED:
            raise ValueError("فقط تایم‌شیت‌های ارسال‌شده قابل رد هستند")
        self.status = TimesheetStatus.REJECTED


# ─── Project Member ──────────────────────────────────────────────────

@dataclass
class ProjectMember(TenantEntity):
    """
    عضو پروژه — ارتباط User با Project.
    """
    project_id: UUID = field(default_factory=uuid4)
    user_id: UUID = field(default_factory=uuid4)     # → User

    role: MemberRole = MemberRole.MEMBER
    is_active: bool = True

    joined_date: Optional[date] = None
    left_date: Optional[date] = None
    notes: str = ""


# ─── Comment ─────────────────────────────────────────────────────────

@dataclass
class Comment(TenantEntity):
    """
    نظر/بحث روی تسک یا پروژه.
    """
    project_id: UUID = field(default_factory=uuid4)
    task_id: Optional[UUID] = None          # null = نظر سطح پروژه
    user_id: UUID = field(default_factory=uuid4)     # → User

    content: str = ""
    parent_id: Optional[UUID] = None        # reply to another comment
    mentions: Optional[list] = field(default_factory=list)  # [UUID] — user IDs mentioned

    is_edited: bool = False
    is_deleted: bool = False


# ─── Activity Log ────────────────────────────────────────────────────

@dataclass
class ActivityLog(TenantEntity):
    """
    لاگ فعالیت‌ها — تایم‌لاین فعالیت‌ها.
    """
    project_id: UUID = field(default_factory=uuid4)
    task_id: Optional[UUID] = None
    user_id: Optional[UUID] = None           # → User

    action: str = ""              # created, updated, completed, assigned, ...
    entity_type: str = ""         # project, task, risk, ...
    entity_id: Optional[UUID] = None

    description: str = ""
    changes: Optional[dict] = field(default_factory=dict)  # {field: {old, new}}
    ip_address: str = ""
