from __future__ import annotations

from dataclasses import dataclass, field
from datetime import date, time
from typing import Optional


@dataclass(frozen=True)
class LeaveEvent:
    """请假/调休等工时事件，key 用于跨天重复记录去重。"""

    kind: str
    start_text: str
    end_text: str
    hours: float

    @property
    def key(self) -> tuple[str, str, str, float]:
        return (self.kind, self.start_text, self.end_text, round(self.hours, 4))


@dataclass
class DailyAttendance:
    """单个员工某一天的考勤明细。"""

    work_date: date
    raw_text: str = ""
    first_punch: Optional[time] = None
    last_punch: Optional[time] = None
    late_minutes: list[int] = field(default_factory=list)
    missing_card_count: int = 0
    leave_events: list[LeaveEvent] = field(default_factory=list)
    punch_overtime_hours: float = 0.0

    @property
    def leave_hours_in_cell(self) -> float:
        return sum(event.hours for event in self.leave_events)


@dataclass
class EmployeeAttendance:
    """员工月度考勤数据，包含汇总字段和每日明细。"""

    name: str
    attendance_group: str = ""
    department: str = ""
    employee_no: str = ""
    position: str = ""
    user_id: str = ""
    summary_fields: dict[str, float | str] = field(default_factory=dict)
    daily_records: list[DailyAttendance] = field(default_factory=list)

    @property
    def unique_leave_events(self) -> list[LeaveEvent]:
        seen: set[tuple[str, str, str, float]] = set()
        result: list[LeaveEvent] = []
        for record in self.daily_records:
            for event in record.leave_events:
                if event.key not in seen:
                    seen.add(event.key)
                    result.append(event)
        return result


@dataclass(frozen=True)
class EmployeePayConfig:
    """员工工资配置；计算器只关心规则值，不关心这些值来自数据库还是配置文件。"""

    salary_mode: str = "monthly"
    base_salary: Optional[float] = None
    hourly_rate: float = 0.0
    piece_quantity: float = 0.0
    piece_unit_price: float = 0.0
    probation_type: str = "ratio"
    probation_ratio: float = 1.0
    probation_salary: Optional[float] = None
    commission_amount: float = 0.0
    overtime_rate: Optional[float] = None
    weekend_overtime_rate: Optional[float] = None
    holiday_overtime_rate: Optional[float] = None


@dataclass(frozen=True)
class PayrollResult:
    """员工级工资计算结果。"""

    employee: EmployeeAttendance
    salary_month: str
    salary_mode: str
    attendance_days: float
    absence_days: float
    actual_work_hours: float
    punch_overtime_hours: float
    leave_hours: float
    remaining_overtime_hours: float
    workday_overtime_hours: float
    weekend_overtime_hours: float
    holiday_overtime_hours: float
    minor_late_count: int
    major_late_count: int
    penalized_late_count: int
    late_deduction: float
    missing_card_count: int
    missing_card_deduction: float
    total_deduction: float
    base_salary: Optional[float]
    base_pay: Optional[float]
    commission_amount: float
    overtime_rate: float
    weekend_overtime_rate: float
    holiday_overtime_rate: float
    overtime_pay: float
    gross_salary: Optional[float]
    net_salary: Optional[float]
    note: str = ""
