from __future__ import annotations

from sqlalchemy import or_
from sqlalchemy.orm import Session, joinedload

from ..database.orm import EmployeeORM, SalaryProfileORM


class SalaryProfileRepository:
    """薪资档案仓库：维护 salary_profiles 表和员工关联查询。"""

    def __init__(self, session: Session):
        self.session = session

    def upsert_profile(
        self,
        *,
        employee_id: int,
        salary_mode: str,
        base_salary: float,
        hourly_rate: float,
        piece_quantity: float,
        piece_unit_price: float,
        probation_type: str,
        probation_ratio: float,
        probation_salary: float,
        commission_amount: float,
        overtime_rate: float,
        weekend_overtime_rate: float,
        holiday_overtime_rate: float,
        effective_month: str = "",
        remark: str = "",
    ) -> SalaryProfileORM:
        profile = self.get_by_employee_id(employee_id)
        if profile is None:
            profile = SalaryProfileORM(employee_id=employee_id)
            self.session.add(profile)

        profile.salary_mode = salary_mode
        profile.base_salary = base_salary
        profile.hourly_rate = hourly_rate
        profile.piece_quantity = piece_quantity
        profile.piece_unit_price = piece_unit_price
        profile.probation_type = probation_type
        profile.probation_ratio = probation_ratio
        profile.probation_salary = probation_salary
        profile.commission_amount = commission_amount
        profile.overtime_rate = overtime_rate
        profile.weekend_overtime_rate = weekend_overtime_rate
        profile.holiday_overtime_rate = holiday_overtime_rate
        profile.effective_month = effective_month
        profile.remark = remark
        self.session.commit()
        self.session.refresh(profile)
        return self.require_by_employee_id(employee_id)

    def get_by_employee_id(self, employee_id: int) -> SalaryProfileORM | None:
        return (
            self.session.query(SalaryProfileORM)
            .options(joinedload(SalaryProfileORM.employee))
            .filter(SalaryProfileORM.employee_id == employee_id)
            .one_or_none()
        )

    def require_by_employee_id(self, employee_id: int) -> SalaryProfileORM:
        profile = self.get_by_employee_id(employee_id)
        if profile is None:
            raise ValueError("薪资档案不存在")
        return profile

    def list_profiles(self, *, keyword: str | None = None) -> list[SalaryProfileORM]:
        query = self.session.query(SalaryProfileORM).options(joinedload(SalaryProfileORM.employee))
        if keyword:
            like_keyword = f"%{keyword}%"
            query = query.join(SalaryProfileORM.employee).filter(
                or_(
                    EmployeeORM.employee_no.like(like_keyword),
                    EmployeeORM.name.like(like_keyword),
                    EmployeeORM.department.like(like_keyword),
                    EmployeeORM.position.like(like_keyword),
                )
            )
        return query.order_by(SalaryProfileORM.updated_at.desc(), SalaryProfileORM.id.desc()).all()

    def list_active_profiles(self) -> list[SalaryProfileORM]:
        return (
            self.session.query(SalaryProfileORM)
            .join(SalaryProfileORM.employee)
            .options(joinedload(SalaryProfileORM.employee))
            .filter(EmployeeORM.employment_status == "active")
            .order_by(SalaryProfileORM.id.asc())
            .all()
        )
