from __future__ import annotations

from datetime import date, datetime

from pydantic import BaseModel, ConfigDict, EmailStr, Field


def _parse_optional_date(value: str | None, label: str) -> date | None:
    if not value:
        return None

    try:
        return datetime.strptime(value, "%Y-%m-%d").date()
    except ValueError as exc:
        raise ValueError(f"{label}格式必须为 YYYY-MM-DD。") from exc


class EmployeeHistoryRead(BaseModel):
    action: str
    owner: str
    time: str
    occurredAt: str


class EmployeeOrganizationRead(BaseModel):
    id: str
    code: str
    name: str
    unitType: str
    costCenter: str | None = None
    location: str | None = None
    managerName: str | None = None


class EmployeeRoleOptionRead(BaseModel):
    id: str
    code: str
    label: str
    desc: str
    permissions: list[str] = Field(default_factory=list)


class EmployeeStatusSummaryRead(BaseModel):
    id: str
    label: str
    count: int


class EmployeeMetaRead(BaseModel):
    totalEmployees: int
    statusSummary: list[EmployeeStatusSummaryRead]
    roleOptions: list[EmployeeRoleOptionRead]
    organizationOptions: list[EmployeeOrganizationRead] = Field(default_factory=list)


class EmployeeRead(BaseModel):
    model_config = ConfigDict(from_attributes=False)

    id: str
    avatar: str
    name: str
    employeeNo: str
    department: str
    position: str
    grade: str
    manager: str
    managerEmployeeNo: str | None = None
    financeOwner: str
    roles: list[str] = Field(default_factory=list)
    roleCodes: list[str] = Field(default_factory=list)
    status: str
    statusTone: str
    gender: str | None = None
    age: int | None = None
    birthDate: str | None = None
    email: EmailStr
    phone: str | None = None
    joinDate: str | None = None
    location: str | None = None
    costCenter: str | None = None
    bankName: str | None = None
    bankAccountNo: str | None = None
    bankAccountName: str | None = None
    updatedAt: str | None = None
    lastSync: str | None = None
    syncState: str
    spotlight: bool = False
    permissions: list[str] = Field(default_factory=list)
    history: list[EmployeeHistoryRead] = Field(default_factory=list)
    organization: EmployeeOrganizationRead | None = None


class EmployeeCreate(BaseModel):
    employee_no: str = Field(min_length=1, max_length=50)
    name: str = Field(min_length=1, max_length=100)
    email: EmailStr
    gender: str | None = Field(default=None, max_length=20)
    birth_date: str | None = None
    phone: str | None = Field(default=None, max_length=30)
    join_date: str | None = None
    location: str | None = Field(default=None, max_length=100)
    position: str = Field(default="员工", max_length=100)
    grade: str = Field(default="P3", max_length=20)
    cost_center: str | None = Field(default=None, max_length=50)
    finance_owner_name: str | None = Field(default=None, max_length=100)
    bank_name: str | None = Field(default=None, max_length=120)
    bank_account_no: str | None = Field(default=None, max_length=80)
    bank_account_name: str | None = Field(default=None, max_length=100)
    employment_status: str = Field(default="在职", max_length=30)
    sync_state: str = Field(default="已同步", max_length=30)
    spotlight: bool = False
    organization_unit_code: str | None = Field(default=None, max_length=50)
    manager_employee_no: str | None = Field(default=None, max_length=50)
    role_codes: list[str] = Field(default_factory=lambda: ["user"])

    def parsed_birth_date(self) -> date | None:
        return _parse_optional_date(self.birth_date, "出生日期")

    def parsed_join_date(self) -> date | None:
        return _parse_optional_date(self.join_date, "入职日期")


class EmployeeImportErrorRead(BaseModel):
    row: int
    column: str
    employeeNo: str = ""
    message: str


class EmployeeImportSummaryRead(BaseModel):
    totalRows: int = 0
    created: int = 0
    updated: int = 0
    errorCount: int = 0


class EmployeeImportResultRead(BaseModel):
    success: bool
    message: str
    summary: EmployeeImportSummaryRead
    errors: list[EmployeeImportErrorRead] = Field(default_factory=list)
    importedAt: str | None = None


class EmployeeUpdate(BaseModel):
    name: str | None = Field(default=None, min_length=1, max_length=100)
    gender: str | None = Field(default=None, max_length=20)
    birth_date: str | None = None
    phone: str | None = Field(default=None, max_length=30)
    email: EmailStr | None = None
    join_date: str | None = None
    location: str | None = Field(default=None, max_length=100)
    position: str | None = Field(default=None, min_length=1, max_length=100)
    grade: str | None = Field(default=None, min_length=1, max_length=20)
    cost_center: str | None = Field(default=None, max_length=50)
    finance_owner_name: str | None = Field(default=None, max_length=100)
    bank_name: str | None = Field(default=None, max_length=120)
    bank_account_no: str | None = Field(default=None, max_length=80)
    bank_account_name: str | None = Field(default=None, max_length=100)
    organization_unit_code: str | None = Field(default=None, max_length=50)
    manager_employee_no: str | None = Field(default=None, max_length=50)
    role_codes: list[str] | None = None
    password: str | None = Field(default=None, min_length=5, max_length=128)

    def parsed_birth_date(self) -> date | None:
        return _parse_optional_date(self.birth_date, "出生日期")

    def parsed_join_date(self) -> date | None:
        return _parse_optional_date(self.join_date, "入职日期")
