# xll_kit/cruds/mixins/batch_upsert_mixin.py
from typing import List, Dict, Any

from sqlalchemy import select
from sqlalchemy.orm import Session


class BatchUpsertMixin:
    def batch_upsert(
            self,
            session: Session,
            data_list: List[Dict[str, Any]],
            unique_keys: List[str],
            *,
            scope_filter=None,
    ):
        """
        批量 upsert
        :param session:
        :param data_list:
        :param unique_keys:
        :param scope_filter:
            scope_filter=(
                OrderItem.order_id == order_id
            )
            scope_filter = and_(
                Sales.platform == platform,
                Sales.stat_date == stat_date,
            )
        :return:
        """
        model = self.model

        # 1️⃣ 查询本次同步范围内的所有旧数据（含将被删除的）
        query = select(model)
        if scope_filter is not None:
            query = query.where(scope_filter)

        existing_objs = session.execute(query).scalars().all()

        # 2️⃣ 构建索引
        existing_map = {
            tuple(getattr(obj, k) for k in unique_keys): obj
            for obj in existing_objs
        }

        # 3️⃣ 先统一 soft_delete
        for obj in existing_objs:
            # soft delete 逻辑
            if hasattr(obj, "is_deleted"):
                obj.is_deleted = True

        # 4️⃣ upsert
        for data in data_list:
            key = tuple(data[k] for k in unique_keys)

            if key in existing_map:
                obj = existing_map[key]
                for k, v in data.items():
                    setattr(obj, k, v)
                # soft delete 逻辑
                if hasattr(obj, "is_deleted"):
                        obj.is_deleted = False
            else:
                obj = model(**data)
                obj.is_deleted = False
                session.add(obj)

        session.flush()
