"""
Employee - Domain Entity

اطلاعات اصلی کارمند شامل مشخصات فردی و استخدامی.
"""
from dataclasses import dataclass, field
from datetime import date, datetime
from typing import Optional, List
from uuid import UUID, uuid4

from shared.base_classes.entity import TenantEntity


class EmploymentStatus:
    """وضعیت استخدامی."""
    ACTIVE = "ACTIVE"
    ON_LEAVE = "ON_LEAVE"
    SUSPENDED = "SUSPENDED"
    TERMINATED = "TERMINATED"
    RETIRED = "RETIRED"
    PROBATION = "PROBATION"


class Gender:
    """جنسیت."""
    MALE = "MALE"
    FEMALE = "FEMALE"


class MaritalStatus:
    """وضعیت تأهل."""
    SINGLE = "SINGLE"
    MARRIED = "MARRIED"
    DIVORCED = "DIVORCED"
    WIDOWED = "WIDOWED"


class MilitaryStatus:
    """وضعیت نظام وظیفه."""
    COMPLETED = "COMPLETED"
    EXEMPT = "EXEMPT"
    EDUCATIONAL_EXEMPT = "EDUCATIONAL_EXEMPT"
    ACTIVE = "ACTIVE"
    NOT_APPLICABLE = "NOT_APPLICABLE"


@dataclass
class Employee(TenantEntity):
    """
    کارمند - Aggregate Root.

    شامل اطلاعات شناسایی، تماس و وضعیت استخدامی.
    هر تغییر وضعیت باید از طریق domain events اطلاع‌رسانی شود.

    Rules:
    - کد پرسنلی باید یکتا در هر tenant باشد
    - کد ملی باید معتبر باشد
    - تاریخ استخدام نمی‌تواند در آینده باشد
    - خاتمه همکاری فقط برای کارمندان فعال
    """

    # Personal Information
    employee_code: str = ""
    first_name: str = ""
    last_name: str = ""
    first_name_en: str = ""
    last_name_en: str = ""
    national_code: str = ""
    birth_certificate_number: str = ""
    date_of_birth: Optional[date] = None
    gender: str = Gender.MALE
    marital_status: str = MaritalStatus.SINGLE
    military_status: str = MilitaryStatus.NOT_APPLICABLE
    nationality: str = "IR"

    # Contact Information
    phone: str = ""
    mobile: str = ""
    email: str = ""
    address: str = ""
    postal_code: str = ""
    city: str = ""
    province: str = ""

    # Emergency Contact
    emergency_contact_name: str = ""
    emergency_contact_phone: str = ""
    emergency_contact_relation: str = ""

    # Employment Information
    user_id: Optional[UUID] = None
    hire_date: Optional[date] = None
    termination_date: Optional[date] = None
    employment_status: str = EmploymentStatus.PROBATION
    employment_type: str = "FULL_TIME"  # FULL_TIME, PART_TIME, CONTRACT, INTERN
    probation_end_date: Optional[date] = None

    # Organization
    legal_entity_id: Optional[UUID] = None
    org_unit_id: Optional[UUID] = None
    location_id: Optional[UUID] = None
    primary_position_id: Optional[UUID] = None
    manager_id: Optional[UUID] = None

    # System
    is_active: bool = True
    metadata: dict = field(default_factory=dict)

    @property
    def full_name(self) -> str:
        """نام کامل فارسی."""
        return f"{self.first_name} {self.last_name}".strip()

    @property
    def full_name_en(self) -> str:
        """نام کامل انگلیسی."""
        return f"{self.first_name_en} {self.last_name_en}".strip()

    def validate(self) -> None:
        """اعتبارسنجی قوانین کسب‌وکار."""
        if not self.employee_code:
            raise ValueError("کد پرسنلی الزامی است")
        if not self.first_name:
            raise ValueError("نام الزامی است")
        if not self.last_name:
            raise ValueError("نام خانوادگی الزامی است")
        if not self.national_code:
            raise ValueError("کد ملی الزامی است")
        if len(self.national_code) != 10:
            raise ValueError("کد ملی باید ۱۰ رقم باشد")
        if self.hire_date and self.hire_date > date.today():
            raise ValueError("تاریخ استخدام نمی‌تواند در آینده باشد")

    def can_terminate(self) -> bool:
        """بررسی امکان خاتمه همکاری."""
        return self.employment_status in (
            EmploymentStatus.ACTIVE,
            EmploymentStatus.PROBATION,
            EmploymentStatus.SUSPENDED,
        )

    def terminate(self, termination_date: date, reason: str = "") -> None:
        """خاتمه همکاری کارمند."""
        if not self.can_terminate():
            raise ValueError(
                f"خاتمه همکاری در وضعیت {self.employment_status} امکان‌پذیر نیست"
            )
        self.employment_status = EmploymentStatus.TERMINATED
        self.termination_date = termination_date
        self.is_active = False
        self.mark_updated()

    def activate(self) -> None:
        """فعال‌سازی کارمند پس از دوره آزمایشی."""
        if self.employment_status != EmploymentStatus.PROBATION:
            raise ValueError("فقط کارمندان در دوره آزمایشی قابل فعال‌سازی هستند")
        self.employment_status = EmploymentStatus.ACTIVE
        self.mark_updated()

    def transfer(self, new_org_unit_id: UUID, new_position_id: Optional[UUID] = None) -> None:
        """انتقال کارمند به واحد سازمانی جدید."""
        if self.employment_status == EmploymentStatus.TERMINATED:
            raise ValueError("کارمندان خاتمه‌یافته قابل انتقال نیستند")
        self.org_unit_id = new_org_unit_id
        if new_position_id:
            self.primary_position_id = new_position_id
        self.mark_updated()

    def suspend(self) -> None:
        """تعلیق کارمند."""
        if self.employment_status != EmploymentStatus.ACTIVE:
            raise ValueError("فقط کارمندان فعال قابل تعلیق هستند")
        self.employment_status = EmploymentStatus.SUSPENDED
        self.mark_updated()
