from __future__ import annotations

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

from ..database.orm import CommissionRecordORM, EmployeeORM


class CommissionRepository:
    """提成仓库：只负责 commission_record 表的读写和月度汇总。"""

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

    def create_record(
        self,
        *,
        employee_id: int,
        commission_month: str,
        commission_type: str,
        amount: float,
        source_type: str,
        business_ref: str,
        remark: str,
    ) -> CommissionRecordORM:
        record = CommissionRecordORM(
            employee_id=employee_id,
            commission_month=commission_month,
            commission_type=commission_type,
            amount=amount,
            source_type=source_type,
            business_ref=business_ref,
            remark=remark,
        )
        self.session.add(record)
        self.session.commit()
        return self.require_by_id(record.id)

    def update_record(
        self,
        record_id: int,
        *,
        employee_id: int,
        commission_month: str,
        commission_type: str,
        amount: float,
        source_type: str,
        business_ref: str,
        remark: str,
    ) -> CommissionRecordORM:
        record = self.require_by_id(record_id)
        record.employee_id = employee_id
        record.commission_month = commission_month
        record.commission_type = commission_type
        record.amount = amount
        record.source_type = source_type
        record.business_ref = business_ref
        record.remark = remark
        self.session.commit()
        return self.require_by_id(record_id)

    def delete_record(self, record_id: int) -> None:
        record = self.require_by_id(record_id)
        self.session.delete(record)
        self.session.commit()

    def require_by_id(self, record_id: int) -> CommissionRecordORM:
        record = (
            self.session.query(CommissionRecordORM)
            .options(joinedload(CommissionRecordORM.employee))
            .filter(CommissionRecordORM.id == record_id)
            .one_or_none()
        )
        if record is None:
            raise ValueError("提成记录不存在")
        return record

    def list_records(
        self,
        *,
        page: int,
        page_size: int,
        commission_month: str | None = None,
        keyword: str | None = None,
    ) -> tuple[list[CommissionRecordORM], int]:
        query = self.session.query(CommissionRecordORM).options(joinedload(CommissionRecordORM.employee))
        if commission_month:
            query = query.filter(CommissionRecordORM.commission_month == commission_month)
        if keyword:
            like_keyword = f"%{keyword}%"
            query = query.join(CommissionRecordORM.employee).filter(
                or_(
                    EmployeeORM.employee_no.like(like_keyword),
                    EmployeeORM.name.like(like_keyword),
                    EmployeeORM.department.like(like_keyword),
                    CommissionRecordORM.commission_type.like(like_keyword),
                    CommissionRecordORM.business_ref.like(like_keyword),
                )
            )
        total = query.count()
        items = (
            query.order_by(CommissionRecordORM.commission_month.desc(), CommissionRecordORM.id.desc())
            .offset((page - 1) * page_size)
            .limit(page_size)
            .all()
        )
        return items, total

    def aggregate_by_month(self, commission_month: str) -> dict[int, float]:
        rows = (
            self.session.query(CommissionRecordORM.employee_id, func.sum(CommissionRecordORM.amount))
            .filter(CommissionRecordORM.commission_month == commission_month)
            .group_by(CommissionRecordORM.employee_id)
            .all()
        )
        return {employee_id: float(amount or 0) for employee_id, amount in rows}

    def create_many(self, records: list[CommissionRecordORM]) -> int:
        self.session.add_all(records)
        self.session.commit()
        return len(records)
