package jnpf.attendance.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jnpf.attendance.antifreeze.UserAntifreeze;
import jnpf.attendance.mapper.WorkstationMapper;
import jnpf.attendance.mapper.WorkstationUserMapper;
import jnpf.attendance.service.AttendanceDailyRuleService;
import jnpf.attendance.service.AttendanceGroupService;
import jnpf.attendance.service.AttendanceUserService;
import jnpf.attendance.service.WorkstationService;
import jnpf.authority.FtbAuthorityApi;
import jnpf.base.service.SuperServiceImpl;
import jnpf.entity.AttendanceGroup;
import jnpf.entity.AttendanceGroupUser;
import jnpf.entity.Workstation;
import jnpf.entity.WorkstationUser;
import jnpf.model.attendance.dto.WorkstationQueryDto;
import jnpf.model.attendance.dto.WorkstationSaveDto;
import jnpf.model.attendance.dto.WorkstationUserAddDto;
import jnpf.model.attendance.dto.WorkstationUserRemoveDto;
import jnpf.model.attendance.vo.*;
import jnpf.permission.model.user.PartUserInfoVo;
import jnpf.permission.vo.store.StoreBaseListInfo;
import jnpf.util.DateDetail;
import jnpf.util.RandomUtil;
import jnpf.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 考勤工作站服务实现
 *
 * @author AI Generated
 * @create 2026-05-11
 */
@Slf4j
@Service
public class WorkstationServiceImpl extends SuperServiceImpl<WorkstationMapper, Workstation> implements WorkstationService {

    private static final int MAX_IN_GROUP_QUERY_DAYS = 366;

    @Resource
    private WorkstationUserMapper workstationUserMapper;


    @Resource
    private AttendanceGroupService attendanceGroupService;

    @Resource
    private AttendanceUserService attendanceUserService;

    @Resource
    private UserAntifreeze userAntifreeze;
    @Resource
    private FtbAuthorityApi ftbAuthorityApi;

    @Autowired
    private AttendanceDailyRuleService attendanceDailyRuleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveWorkstation(WorkstationSaveDto dto) {
        assertWorkstationUniqueUnderStore(dto.getStoreId(), dto.getName(), dto.getPositionId(), null);

        Workstation workstation = new Workstation();
        BeanUtils.copyProperties(dto, workstation);
        workstation.setId(RandomUtil.uuId());
        workstation.setCreatorUserId(UserProvider.getUser().getUserId());
        workstation.setCreatorTime(new Date());
        workstation.setTenantId(UserProvider.getUser().getTenantId());
        workstation.setDeleteMark(0);
        workstation.setEnabledMark(1);
        if (workstation.getSortCode() == null) {
            workstation.setSortCode(0);
        }

        this.save(workstation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWorkstation(String id, WorkstationSaveDto dto) {
        Workstation workstation = this.getById(id);
        Assert.notNull(workstation, "工作站不存在");

        assertWorkstationUniqueUnderStore(dto.getStoreId(), dto.getName(), dto.getPositionId(), id);

        BeanUtils.copyProperties(dto, workstation);
        workstation.setLastModifyUserId(UserProvider.getUser().getUserId());
        workstation.setLastModifyTime(new Date());

        this.updateById(workstation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWorkstation(String id) {
        Workstation workstation = this.getById(id);
        Assert.notNull(workstation, "工作站不存在");

        // 软删除工作站
        workstation.setDeleteMark(1);
        workstation.setDeleteUserId(UserProvider.getUser().getUserId());
        workstation.setDeleteTime(new Date());
        this.updateById(workstation);

        // 级联删除关联人员
        LambdaQueryWrapper<WorkstationUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WorkstationUser::getWorkstationId, id)
               .eq(WorkstationUser::getDeleteMark, 0);
        List<WorkstationUser> userList = workstationUserMapper.selectList(wrapper);
        if (CollUtil.isNotEmpty(userList)) {
            String deleteUserId = UserProvider.getUser().getUserId();
            Date deleteTime = new Date();
            userList.forEach(user -> {
                user.setDeleteMark(1);
                user.setDeleteUserId(deleteUserId);
                user.setDeleteTime(deleteTime);
                workstationUserMapper.updateById(user);
            });
        }
    }

    @Override
    public PageInfo<WorkstationVo> listWorkstations(WorkstationQueryDto dto) {
        LambdaQueryWrapper<Workstation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Workstation::getDeleteMark, 0);
        if(Objects.equals(dto.getHasAuth(),1)){
            List<StoreBaseListInfo> storeBaseListInfos = ftbAuthorityApi.authStoreBaseListInfo();
            wrapper.in(Workstation::getStoreId, storeBaseListInfos.stream().map(StoreBaseListInfo::getId).distinct().collect(Collectors.toList()));
        }
        if (StringUtils.isNotBlank(dto.getKeyword())) {
            wrapper.and(v->v.like(Workstation::getName, dto.getKeyword())
                    .or()
                    .like(Workstation::getStoreName, dto.getKeyword()));
        }
        if (StringUtils.isNotBlank(dto.getName())) {
            wrapper.like(Workstation::getName, dto.getName());
        }
        if (StringUtils.isNotBlank(dto.getStoreId())) {
            wrapper.eq(Workstation::getStoreId, dto.getStoreId());
        }
        if (StringUtils.isNotBlank(dto.getPositionId())) {
            wrapper.eq(Workstation::getPositionId, dto.getPositionId());
        }

        wrapper.orderByAsc(Workstation::getSortCode)
               .orderByDesc(Workstation::getCreatorTime);

        PageHelper.startPage(dto.getCurrentPage(), dto.getPageSize());
        PageInfo<Workstation> entityPage = new PageInfo<>(this.list(wrapper));

        List<WorkstationVo> voList = entityPage.getList().stream().map(w -> {
            WorkstationVo vo = new WorkstationVo();
            BeanUtils.copyProperties(w, vo);
            return vo;
        }).collect(Collectors.toList());

        PageInfo<WorkstationVo> result = new PageInfo<>();
        BeanUtils.copyProperties(entityPage, result);
        result.setList(voList);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUsers(WorkstationUserAddDto dto) {
        requireActiveWorkstation(dto.getWorkstationId());

        // 批量添加人员(幂等操作)
        String tenantId = UserProvider.getUser().getTenantId();
        String userId = UserProvider.getUser().getUserId();
        Date now = new Date();

        for (String addUserId : dto.getUserIds()) {
            // 检查是否已存在
            LambdaQueryWrapper<WorkstationUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WorkstationUser::getWorkstationId, dto.getWorkstationId())
                   .eq(WorkstationUser::getUserId, addUserId)
                   .eq(WorkstationUser::getDeleteMark, 0);
            long count = workstationUserMapper.selectCount(wrapper);
            if (count > 0) {
                continue; // 已存在，跳过
            }

            WorkstationUser workstationUser = new WorkstationUser();
            workstationUser.setId(RandomUtil.uuId());
            workstationUser.setWorkstationId(dto.getWorkstationId());
            workstationUser.setUserId(addUserId);
            workstationUser.setCreatorUserId(userId);
            workstationUser.setCreatorTime(now);
            workstationUser.setTenantId(tenantId);
            workstationUser.setDeleteMark(0);

            workstationUserMapper.insert(workstationUser);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeUser(WorkstationUserRemoveDto dto) {
        requireActiveWorkstation(dto.getWorkstationId());

        // 查找关联记录
        LambdaQueryWrapper<WorkstationUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WorkstationUser::getWorkstationId, dto.getWorkstationId())
               .eq(WorkstationUser::getUserId, dto.getUserId())
               .eq(WorkstationUser::getDeleteMark, 0);
        WorkstationUser workstationUser = workstationUserMapper.selectOne(wrapper);
        Assert.notNull(workstationUser, "该人员不存在于工作站中");

        // 软删除
        workstationUser.setDeleteMark(1);
        workstationUser.setDeleteUserId(UserProvider.getUser().getUserId());
        workstationUser.setDeleteTime(new Date());
        workstationUserMapper.updateById(workstationUser);
    }

    @Override
    public WorkstationDetailVo getDetail(String id) {
        Workstation workstation = this.getById(id);
        Assert.notNull(workstation, "工作站不存在");

        WorkstationDetailVo detailVo = new WorkstationDetailVo();
        BeanUtils.copyProperties(workstation, detailVo);
        detailVo.setUserList(buildDetailUserList(workstation));
        return detailVo;
    }

    /**
     * 组装工作站详情关联人员：含岗位默认归属（主岗位匹配）与关联表另加入员工，并以 {@code isExtra} 区分。
     */
    private List<WorkstationUserVo> buildDetailUserList(Workstation workstation) {
        List<AttendanceGroup> byOrgId = attendanceGroupService.getByOrgId(workstation.getStoreId());
        if (CollUtil.isEmpty(byOrgId)){
            return buildDetailUserListFromRelations(workstation.getId());
        }
        Date snapshotEnd = new Date();
        List<AttendanceGroupUser> groupUsers = attendanceUserService.getAttendanceGroupUsersOfSecondment(
                snapshotEnd, snapshotEnd, null, byOrgId.stream().map(AttendanceGroup::getId).distinct().collect(Collectors.toList()));
        List<String> groupUserIds = CollUtil.isEmpty(groupUsers) ? CollUtil.newArrayList() :
                groupUsers.stream()
                        .map(AttendanceGroupUser::getUserId)
                        .filter(StrUtil::isNotEmpty)
                        .distinct()
                        .collect(Collectors.toList());

        Set<String> extraUserIds = loadExtraUserIdsByWorkstation(List.of(workstation.getId()), groupUserIds)
                .getOrDefault(workstation.getId(), new HashSet<>());
        Map<String, PartUserInfoVo> userInfoMap = batchGetUserInfoMap(
                new ArrayList<>(CollUtil.unionDistinct(groupUserIds, extraUserIds)));

        List<WorkstationUserVo> userList = new ArrayList<>();
        Set<String> appendedUserIds = new HashSet<>();

        if (StrUtil.isNotEmpty(workstation.getPositionId()) && CollUtil.isNotEmpty(groupUserIds)) {
            for (String uid : groupUserIds) {
                PartUserInfoVo info = userInfoMap.get(uid);
                if (Objects.nonNull(info) && Objects.equals(workstation.getPositionId(), info.getPositionId())) {
                    userList.add(toWorkstationUserVo(uid, info, Boolean.FALSE));
                    appendedUserIds.add(uid);
                }
            }
        }

        for (String uid : extraUserIds) {
            if (appendedUserIds.contains(uid)) {
                continue;
            }
            userList.add(toWorkstationUserVo(uid, userInfoMap.get(uid), Boolean.TRUE));
            appendedUserIds.add(uid);
        }
        return userList;
    }

    /**
     * 无考勤组上下文时，仅返回关联表中另加入的员工。
     */
    private List<WorkstationUserVo> buildDetailUserListFromRelations(String workstationId) {
        List<WorkstationUser> relations = workstationUserMapper.selectList(
                new LambdaQueryWrapper<WorkstationUser>()
                        .eq(WorkstationUser::getWorkstationId, workstationId)
                        .eq(WorkstationUser::getDeleteMark, 0));
        if (CollUtil.isEmpty(relations)) {
            return CollUtil.newArrayList();
        }

        List<String> userIds = relations.stream()
                .map(WorkstationUser::getUserId)
                .collect(Collectors.toList());
        Map<String, PartUserInfoVo> userInfoMap = batchGetUserInfoMap(userIds);
        return relations.stream()
                .map(rel -> toWorkstationUserVo(rel.getUserId(), userInfoMap.get(rel.getUserId()), Boolean.TRUE))
                .collect(Collectors.toList());
    }

    private WorkstationUserVo toWorkstationUserVo(String userId, PartUserInfoVo info, Boolean isExtra) {
        WorkstationUserVo userVo = new WorkstationUserVo();
        userVo.setUserId(userId);
        userVo.setIsExtra(isExtra);
        if (Objects.nonNull(info)) {
            userVo.setUserName(info.getRealName());
            userVo.setHeadIcon(StrUtil.isNotEmpty(info.getHeadIcon()) ? info.getHeadIcon() : null);
            userVo.setPositionId(info.getPositionId());
            userVo.setPositionName(info.getPositionName());
        } else {
            userVo.setUserName("");
        }
        return userVo;
    }

    @Override
    public List<WorkstationWithUsersVo> listWorkstationsByGroupId(String groupId, Date startTime, Date endTime) {
        if (StrUtil.isEmpty(groupId)) {
            return CollUtil.newArrayList();
        }
        Assert.notNull(startTime, "开始时间不能为空");
        Assert.notNull(endTime, "结束时间不能为空");
        Date rangeStart = cn.hutool.core.date.DateUtil.beginOfDay(startTime);
        Date rangeEnd = cn.hutool.core.date.DateUtil.endOfDay(endTime);
        Assert.isFalse(rangeStart.after(rangeEnd), "开始时间不能晚于结束时间");
        long dayCount = cn.hutool.core.date.DateUtil.betweenDay(rangeStart, rangeEnd, true) + 1;
        Assert.isTrue(dayCount <= MAX_IN_GROUP_QUERY_DAYS,
                "查询跨度不能超过" + MAX_IN_GROUP_QUERY_DAYS + "天");

        AttendanceGroup group = attendanceGroupService.getById(groupId);
        if (Objects.isNull(group) || Objects.equals(group.getDeleteMark(), 1)) {
            return CollUtil.newArrayList();
        }
        String storeId = group.getOrgId();

        // 1. 查询考勤组归属门店下的全部启用且未删除工作站
        LambdaQueryWrapper<Workstation> wsWrapper = new LambdaQueryWrapper<Workstation>()
                .eq(Workstation::getDeleteMark, 0)
                .eq(StrUtil.isNotEmpty(storeId), Workstation::getStoreId, storeId)
                .orderByAsc(Workstation::getSortCode)
                .orderByDesc(Workstation::getCreatorTime);
        List<Workstation> workstations = this.list(wsWrapper);
        if (CollUtil.isEmpty(workstations)) {
            return CollUtil.newArrayList();
        }

        // 2. 截止 endTime 的考勤组成员（含借调过滤）
        List<AttendanceGroupUser> groupUsers = attendanceUserService.getAttendanceGroupUsersOfSecondment(
                rangeEnd, rangeEnd, null, List.of(groupId), true);
        List<String> groupUserIds = CollUtil.isEmpty(groupUsers) ? CollUtil.newArrayList() :
                groupUsers.stream()
                        .map(AttendanceGroupUser::getUserId)
                        .filter(StrUtil::isNotEmpty)
                        .distinct()
                        .collect(Collectors.toList());

        // 3. 查询时间范围内的成员关系，计算每人 inGroupDays
        List<Date> datesByPeriod = DateDetail.getDatesByPeriod(rangeStart, rangeEnd);
        Map<String, List<String>> inGroupDaysByUserId = buildInGroupDaysByUserId(
                groupId, groupUserIds, rangeStart, rangeEnd, datesByPeriod);

        // 4. 划线排班配置过滤
        List<String> canLineUserIds = new ArrayList<>(groupUserIds);
        attendanceDailyRuleService.lineSchedulesConfigFilter(groupId, canLineUserIds);
        Set<String> canLineUserIdSet = new HashSet<>(canLineUserIds);

        // 5. 批量取用户主岗位与姓名
        Map<String, PartUserInfoVo> userInfoMap = batchGetUserInfoMap(groupUserIds);

        // 6. 查询门店下工作站的额外人员关联，仅取仍在考勤组成员范围内的关系
        Map<String, Set<String>> extraUserIdsByWs = loadExtraUserIdsByWorkstation(
                workstations.stream().map(Workstation::getId).collect(Collectors.toList()),
                groupUserIds);

        Set<String> groupUserIdSet = new HashSet<>(groupUserIds);
        return workstations.stream().map(ws -> buildWorkstationWithUsersVo(
                ws, groupUserIdSet, userInfoMap, extraUserIdsByWs.getOrDefault(ws.getId(), new HashSet<>()),
                canLineUserIdSet, inGroupDaysByUserId)
        ).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetWorkstationUsers(String workstationId) {
        Assert.notEmpty(workstationId, "工作站ID不能为空");
        Workstation workstation = this.getById(workstationId);
        Assert.notNull(workstation, "工作站不存在");
        if (Objects.equals(workstation.getDeleteMark(), 1)) {
            return;
        }

        List<WorkstationUser> relations = workstationUserMapper.selectList(
                new LambdaQueryWrapper<WorkstationUser>()
                        .eq(WorkstationUser::getDeleteMark, 0)
                        .eq(WorkstationUser::getWorkstationId, workstationId));
        if (CollUtil.isEmpty(relations)) {
            return;
        }

        String deleteUserId = UserProvider.getUser().getUserId();
        Date deleteTime = new Date();
        for (WorkstationUser relation : relations) {
            relation.setDeleteMark(1);
            relation.setDeleteUserId(deleteUserId);
            relation.setDeleteTime(deleteTime);
            workstationUserMapper.updateById(relation);
        }
    }

    private Map<String, List<String>> buildInGroupDaysByUserId(String groupId, List<String> groupUserIds,
            Date rangeStart, Date rangeEnd, List<Date> datesByPeriod) {
        Map<String, List<String>> result = new HashMap<>();
        if (CollUtil.isEmpty(groupUserIds)) {
            return result;
        }
        List<AttendanceGroupUser> historyUsers = attendanceUserService.getAttendanceGroupUsersOfSecondment(
                rangeStart, rangeEnd, null, List.of(groupId), true);
        Map<String, List<AttendanceGroupUser>> groupUserMap = CollUtil.isEmpty(historyUsers)
                ? new HashMap<>()
                : historyUsers.stream().collect(Collectors.groupingBy(AttendanceGroupUser::getUserId));
        for (String userId : groupUserIds) {
            result.put(userId, resolveInGroupDays(groupUserMap.get(userId), datesByPeriod));
        }
        return result;
    }

    private List<String> resolveInGroupDays(List<AttendanceGroupUser> userRecords, List<Date> datesByPeriod) {
        if (CollUtil.isEmpty(userRecords) || CollUtil.isEmpty(datesByPeriod)) {
            return CollUtil.newArrayList();
        }
        List<String> inGroupDays = new ArrayList<>();
        for (Date day : datesByPeriod) {
            if (isUserInGroupOnDay(userRecords, day)) {
                inGroupDays.add(DateDetail.getDate2Str(day, DateDetail.DF));
            }
        }
        return inGroupDays;
    }

    private boolean isUserInGroupOnDay(List<AttendanceGroupUser> userRecords, Date day) {
        Integer existStatus = attendanceDailyRuleService.isExistStatus(userRecords, day);
        if (Objects.equals(existStatus, 4) || Objects.equals(existStatus, 3)) {
            existStatus = 1;
        }
        return Objects.equals(existStatus, 1);
    }

    /**
     * 批量获取用户基础信息（id、userName、positionId、positionName）映射
     */
    private Map<String, PartUserInfoVo> batchGetUserInfoMap(List<String> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return new java.util.HashMap<>();
        }
        List<PartUserInfoVo> result = userAntifreeze.getInfoByIds(userIds,null);
        if (CollUtil.isEmpty(result)) {
            return new java.util.HashMap<>();
        }
        return result.stream()
                .collect(Collectors.toMap(PartUserInfoVo::getUserId, Function.identity(), (a, b) -> a));
    }

    /**
     * 查询每个工作站下显式额外加入且仍在考勤组成员范围内的 userId 集合
     */
    private Map<String, Set<String>> loadExtraUserIdsByWorkstation(List<String> workstationIds, List<String> groupUserIds) {
        Map<String, Set<String>> result = new LinkedHashMap<>();
        if (CollUtil.isEmpty(workstationIds) || CollUtil.isEmpty(groupUserIds)) {
            return result;
        }
        List<WorkstationUser> relations = workstationUserMapper.selectList(
                new LambdaQueryWrapper<WorkstationUser>()
                        .eq(WorkstationUser::getDeleteMark, 0)
                        .in(WorkstationUser::getWorkstationId, workstationIds)
                        .in(WorkstationUser::getUserId, groupUserIds));
        if (CollUtil.isEmpty(relations)) {
            return result;
        }
        for (WorkstationUser rel : relations) {
            result.computeIfAbsent(rel.getWorkstationId(), k -> new HashSet<>()).add(rel.getUserId());
        }
        return result;
    }

    /**
     * 装配单个工作站的对外 VO（含员工列表）
     *
     * @param ws            工作站实体
     * @param groupUserIds  考勤组当前成员集合（用于按主岗位自动归属）
     * @param userInfoMap   用户主岗位/姓名信息映射
     * @param extraUserIds  通过工作站-人员关联表显式额外加入的成员集合（已限定为考勤组成员）
     */
    private WorkstationWithUsersVo buildWorkstationWithUsersVo(Workstation ws,
                                                               Set<String> groupUserIds,
                                                               Map<String, PartUserInfoVo> userInfoMap,
                                                               Set<String> extraUserIds,
                                                               Set<String> canLineUserIdSet,
                                                               Map<String, List<String>> inGroupDaysByUserId) {
        WorkstationWithUsersVo vo = new WorkstationWithUsersVo();
        vo.setWorkstationId(ws.getId());
        vo.setWorkstationName(ws.getName());
        vo.setPositionId(ws.getPositionId());
        vo.setPositionName(ws.getPositionName());

        List<WorkstationGroupUserVo> userList = new ArrayList<>();
        Set<String> appendedUserIds = new HashSet<>();

        // 主岗位与工作站岗位一致 → 自动归属（isExtra=false）
        if (StrUtil.isNotEmpty(ws.getPositionId()) && CollUtil.isNotEmpty(groupUserIds)) {
            for (String uid : groupUserIds) {
                PartUserInfoVo info = userInfoMap.get(uid);
                if (Objects.nonNull(info) && Objects.equals(ws.getPositionId(), info.getPositionId())) {
                    userList.add(toWorkstationGroupUserVo(uid, info, Boolean.FALSE, canLineUserIdSet, inGroupDaysByUserId));
                    appendedUserIds.add(uid);
                }
            }
        }

        // 关联表显式额外加入 → 标记为另加入员工（isExtra=true），主岗位匹配者已在上方，避免重复
        for (String uid : extraUserIds) {
            if (appendedUserIds.contains(uid)) {
                continue;
            }
            userList.add(toWorkstationGroupUserVo(uid, userInfoMap.get(uid), Boolean.TRUE, canLineUserIdSet, inGroupDaysByUserId));
            appendedUserIds.add(uid);
        }
        vo.setUserList(userList);
        return vo;
    }

    private WorkstationGroupUserVo toWorkstationGroupUserVo(String userId, PartUserInfoVo info, Boolean isExtra,
            Set<String> canLineUserIdSet, Map<String, List<String>> inGroupDaysByUserId) {
        WorkstationGroupUserVo userVo = new WorkstationGroupUserVo();
        userVo.setUserId(userId);
        if (Objects.nonNull(info)) {
            userVo.setUserName(info.getRealName());
            userVo.setPositionId(info.getPositionId());
        }
        userVo.setIsExtra(isExtra);
        userVo.setCanLineSchedule(canLineUserIdSet.contains(userId));
        userVo.setInGroupDays(inGroupDaysByUserId.getOrDefault(userId, CollUtil.newArrayList()));
        return userVo;
    }

    private Workstation requireActiveWorkstation(String workstationId) {
        Workstation workstation = this.getById(workstationId);
        Assert.notNull(workstation, "工作站不存在");
        Assert.isFalse(Objects.equals(workstation.getDeleteMark(), 1), "该工作站已被删除，请返回上一页重新操作");
        return workstation;
    }

    /**
     * 同组织（门店）下工作站名称、岗位均不可重复；不同组织允许重复。
     *
     * @param storeId     组织/门店 ID（{@link Workstation#getStoreId()}）
     * @param name        工作站名称
     * @param positionId  岗位 ID
     * @param excludeId   排除的工作站 ID（编辑时传）
     */
    private void assertWorkstationUniqueUnderStore(String storeId, String name, String positionId, String excludeId) {
        Assert.notBlank(storeId, "门店ID不能为空");
        String tenantId = UserProvider.getUser().getTenantId();

        LambdaQueryWrapper<Workstation> nameWrapper = new LambdaQueryWrapper<>();
        nameWrapper.eq(Workstation::getName, name)
                .eq(Workstation::getStoreId, storeId)
                .eq(Workstation::getDeleteMark, 0)
                .eq(Workstation::getTenantId, tenantId);
        if (StringUtils.isNotBlank(excludeId)) {
            nameWrapper.ne(Workstation::getId, excludeId);
        }
        Assert.isFalse(this.count(nameWrapper) > 0, "同组织下工作站名称已存在");

        LambdaQueryWrapper<Workstation> positionWrapper = new LambdaQueryWrapper<>();
        positionWrapper.eq(Workstation::getPositionId, positionId)
                .eq(Workstation::getStoreId, storeId)
                .eq(Workstation::getDeleteMark, 0)
                .eq(Workstation::getTenantId, tenantId);
        if (StringUtils.isNotBlank(excludeId)) {
            positionWrapper.ne(Workstation::getId, excludeId);
        }
        Assert.isFalse(this.count(positionWrapper) > 0, "同组织下该岗位已绑定其他工作站");
    }
}
