package com.hotwj.platform.noticeManagerment.noticeSignDocument.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hotwj.platform.config.dispatchTemplate.domain.HotDispatchTemplate;
import com.hotwj.platform.config.dispatchTemplate.mapper.HotDispatchTemplateMapper;
import com.hotwj.platform.driverManagement.driver.domain.HotDriver;
import com.hotwj.platform.driverManagement.driver.mapper.HotDriverMapper;
import com.hotwj.platform.flow.service.ISysFlowService;
import com.hotwj.platform.noticeManagerment.noticeSignDocument.domain.HotNoticeSignDocument;
import com.hotwj.platform.noticeManagerment.noticeSignDocument.domain.bo.HotNoticeSignDocumentBo;
import com.hotwj.platform.noticeManagerment.noticeSignDocument.domain.vo.HotNoticeSignDocumentVo;
import com.hotwj.platform.noticeManagerment.noticeSignDocument.mapper.HotNoticeSignDocumentMapper;
import com.hotwj.platform.noticeManagerment.noticeSignDocument.service.IHotNoticeSignDocumentService;
import com.hotwj.platform.noticeManagerment.signFileDetail.domain.HotSignFileDetail;
import com.hotwj.platform.noticeManagerment.signFileDetail.mapper.HotSignFileDetailMapper;
import com.hotwj.platform.resourceManagement.companySafetyManager.domain.HotCompanySafetyManager;
import com.hotwj.platform.resourceManagement.companySafetyManager.mapper.HotCompanySafetyManagerMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;

/**
 * 签订文件Service业务层处理
 *
 * @author shihongwei
 * @date 2026-01-07
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class HotNoticeSignDocumentServiceImpl implements IHotNoticeSignDocumentService {

    private static final long STAFF_TYPE_DRIVER = 1L;
    private static final long STAFF_TYPE_MANAGER = 2L;
    private static final long STAFF_TYPE_DRIVER_PRACTITIONER = 3L;
    private static final long STAFF_TYPE_ALL = 4L;
    private static final long DEFAULT_NEW_STAFF_ENABLED = 1L;
    private static final long ISSUER_TYPE_DRIVER = 1L;
    private static final long ISSUER_TYPE_MANAGER = 2L;
    private static final long ISSUER_TYPE_DRIVER_PRACTITIONER = 3L;
    private static final long ISSUER_TYPE_ALL = 4L;
    private static final String PERSON_TYPE_DRIVER = "driver";
    private static final String PERSON_TYPE_ESCORT = "escort";
    private static final String HOT_PERSON_TYPE_DRIVER = "1";
    private static final String HOT_PERSON_TYPE_ESCORT = "2";
    private static final DateTimeFormatter VALID_PERIOD_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final HotNoticeSignDocumentMapper baseMapper;
    private final HotSignFileDetailMapper signFileDetailMapper;
    private final HotCompanySafetyManagerMapper safetyManagerMapper;
    private final HotDriverMapper driverMapper;
    private final HotDispatchTemplateMapper dispatchTemplateMapper;
    private final ISysFlowService flowService;

    /**
     * 查询签订文件
     *
     * @param id 主键
     * @return 签订文件
     */
    @Override
    public HotNoticeSignDocumentVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询签订文件列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 签订文件分页列表
     */
    @Override
    public TableDataInfo<HotNoticeSignDocumentVo> queryPageList(HotNoticeSignDocumentBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HotNoticeSignDocument> lqw = buildQueryWrapper(bo);
        Page<HotNoticeSignDocumentVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的签订文件列表
     *
     * @param bo 查询条件
     * @return 签订文件列表
     */
    @Override
    public List<HotNoticeSignDocumentVo> queryList(HotNoticeSignDocumentBo bo) {
        LambdaQueryWrapper<HotNoticeSignDocument> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<HotNoticeSignDocument> buildQueryWrapper(HotNoticeSignDocumentBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HotNoticeSignDocument> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(HotNoticeSignDocument::getId);
        lqw.eq(bo.getCompanyId() != null, HotNoticeSignDocument::getCompanyId, bo.getCompanyId());
        lqw.like(StringUtils.isNotBlank(bo.getFileName()), HotNoticeSignDocument::getFileName, bo.getFileName());
        lqw.eq(bo.getIssuerType() != null, HotNoticeSignDocument::getIssuerType, bo.getIssuerType());
        lqw.eq(bo.getFileType() != null, HotNoticeSignDocument::getFileType, bo.getFileType());
        lqw.eq(bo.getNeedFill() != null, HotNoticeSignDocument::getNeedFill, bo.getNeedFill());
        lqw.eq(bo.getEnableESeal() != null, HotNoticeSignDocument::getEnableESeal, bo.getEnableESeal());
        lqw.eq(bo.getIsDefaultNewStaff() != null, HotNoticeSignDocument::getIsDefaultNewStaff, bo.getIsDefaultNewStaff());
        lqw.eq(bo.getValidType() != null, HotNoticeSignDocument::getValidType, bo.getValidType());
        lqw.eq(StringUtils.isNotBlank(bo.getValidPeriod()), HotNoticeSignDocument::getValidPeriod, bo.getValidPeriod());
        lqw.eq(StringUtils.isNotBlank(bo.getIssuePersonIds()), HotNoticeSignDocument::getIssuePersonIds, bo.getIssuePersonIds());
        lqw.eq(bo.getTemplateId() != null, HotNoticeSignDocument::getTemplateId, bo.getTemplateId());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), HotNoticeSignDocument::getContent, bo.getContent());
        lqw.eq(bo.getIsDeleted() != null, HotNoticeSignDocument::getIsDeleted, bo.getIsDeleted());
        return lqw;
    }

    /**
     * 新增签订文件
     *
     * @param bo 签订文件
     * @return 是否新增成功
     */
    @Override
    public Long insertByBo(HotNoticeSignDocumentBo bo) {
        HotNoticeSignDocument add = MapstructUtils.convert(bo, HotNoticeSignDocument.class);
        add.setSourceCompanyId(resolveSourceCompanyId());
        add.setTemplateNameSnapshot(resolveTemplateNameSnapshot(bo.getTemplateId()));
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return add.getId();
    }

    /**
     * 修改签订文件
     *
     * @param bo 签订文件
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(HotNoticeSignDocumentBo bo) {
        HotNoticeSignDocument old = baseMapper.selectById(bo.getId());
        if (old == null) {
            throw new ServiceException("签订文件不存在");
        }

        Set<String> oldPersonIds = parsePersonIds(old.getIssuePersonIds());
        Set<String> finalPersonIds = normalizePersonIds(oldPersonIds, parsePersonIds(bo.getIssuePersonIds()));
        validateRemovedPersons(old, oldPersonIds, finalPersonIds);

        HotNoticeSignDocument update = MapstructUtils.convert(bo, HotNoticeSignDocument.class);
        update.setIssuePersonIds(String.join(",", finalPersonIds));
        update.setSourceCompanyId(resolveSourceCompanyId());
        if (Objects.equals(old.getTemplateId(), bo.getTemplateId())) {
            update.setTemplateNameSnapshot(old.getTemplateNameSnapshot());
        } else {
            update.setTemplateNameSnapshot(resolveTemplateNameSnapshot(bo.getTemplateId()));
        }
        validEntityBeforeSave(update);
        boolean ok = baseMapper.updateById(update) > 0;
        if (ok) {
            issueNewDetailsAndTodos(old, update, oldPersonIds, finalPersonIds);
        }
        return ok;
    }

    @Override
    public void issueDefaultForNewDriver(HotDriver driver) {
        if (driver == null || StringUtils.isBlank(driver.getId()) || driver.getCompanyId() == null) {
            return;
        }
        if (driver.getIsDeleted() != null && Long.valueOf(1L).equals(driver.getIsDeleted())) {
            return;
        }
        if (driver.getStatus() != null && !Long.valueOf(1L).equals(driver.getStatus())) {
            return;
        }
        String staffId = driver.getId();
        String staffName = driver.getName();
        long staffType = mapDriverStaffType(driver.getPersonType());
        List<Long> issuerTypes = buildIssuerTypesForDriver(driver.getPersonType());
        issueDefaultDocumentsToNewStaff(driver.getCompanyId(), issuerTypes, staffId, staffName, staffType);
    }

    @Override
    public void issueDefaultForNewManager(HotCompanySafetyManager manager) {
        if (manager == null || manager.getId() == null || manager.getCompanyId() == null) {
            return;
        }
        if (manager.getIsDeleted() != null && Long.valueOf(1L).equals(manager.getIsDeleted())) {
            return;
        }
        if (manager.getIsResigned() != null && Long.valueOf(1L).equals(manager.getIsResigned())) {
            return;
        }
        if (manager.getStatus() != null && !Long.valueOf(1L).equals(manager.getStatus())) {
            return;
        }
        String staffId = String.valueOf(manager.getId());
        issueDefaultDocumentsToNewStaff(
                manager.getCompanyId(),
                Arrays.asList(ISSUER_TYPE_MANAGER, ISSUER_TYPE_ALL),
                staffId,
                manager.getName(),
                STAFF_TYPE_MANAGER
        );
    }

    private List<Long> buildIssuerTypesForDriver(String personType) {
        if (isDriverOrEscortPersonType(personType)) {
            return Arrays.asList(ISSUER_TYPE_DRIVER, ISSUER_TYPE_DRIVER_PRACTITIONER, ISSUER_TYPE_ALL);
        }
        return Arrays.asList(ISSUER_TYPE_DRIVER_PRACTITIONER, ISSUER_TYPE_ALL);
    }

    private boolean isDriverOrEscortPersonType(String personType) {
        if (StringUtils.isBlank(personType)) {
            return false;
        }
        String value = personType.trim().toLowerCase(Locale.ROOT);
        return HOT_PERSON_TYPE_DRIVER.equals(value)
                || HOT_PERSON_TYPE_ESCORT.equals(value)
                || PERSON_TYPE_DRIVER.equals(value)
                || PERSON_TYPE_ESCORT.equals(value);
    }

    private void issueDefaultDocumentsToNewStaff(Long companyId, List<Long> issuerTypes, String staffId, String staffName, Long staffType) {
        if (companyId == null || StringUtils.isBlank(staffId) || staffType == null || issuerTypes == null || issuerTypes.isEmpty()) {
            return;
        }
        List<HotNoticeSignDocument> defaultDocs = baseMapper.selectList(
                Wrappers.<HotNoticeSignDocument>lambdaQuery()
                        .eq(HotNoticeSignDocument::getCompanyId, companyId)
                        .eq(HotNoticeSignDocument::getIsDeleted, 0L)
                        .eq(HotNoticeSignDocument::getIsDefaultNewStaff, DEFAULT_NEW_STAFF_ENABLED)
                        .in(HotNoticeSignDocument::getIssuerType, issuerTypes)
        );
        if (defaultDocs == null || defaultDocs.isEmpty()) {
            return;
        }
        for (HotNoticeSignDocument doc : defaultDocs) {
            if (doc == null || doc.getId() == null) {
                continue;
            }
            if (!isWithinValidPeriod(doc)) {
                continue;
            }
            issueDocumentToStaff(doc, staffId, staffName, staffType);
        }
    }

    private boolean isWithinValidPeriod(HotNoticeSignDocument doc) {
        if (doc == null || StringUtils.isBlank(doc.getValidPeriod())) {
            return false;
        }
        try {
            LocalDate expireDate = LocalDate.parse(doc.getValidPeriod().trim(), VALID_PERIOD_FORMATTER);
            return !expireDate.isBefore(LocalDate.now());
        } catch (DateTimeParseException e) {
            log.warn("签订文件有效期格式非法，跳过自动下发。docId={}, validPeriod={}", doc.getId(), doc.getValidPeriod());
            return false;
        }
    }

    private void issueDocumentToStaff(HotNoticeSignDocument doc, String staffId, String staffName, Long staffType) {
        HotSignFileDetail existing = signFileDetailMapper.selectOne(
                Wrappers.<HotSignFileDetail>lambdaQuery()
                        .eq(HotSignFileDetail::getIssueFileId, doc.getId())
                        .eq(HotSignFileDetail::getStaffId, staffId)
                        .eq(HotSignFileDetail::getIsDeleted, 0L)
                        .last("limit 1")
        );
        appendIssuePersonId(doc, staffId);
        String fileName = StringUtils.isNotBlank(doc.getFileName()) ? doc.getFileName() : "未知文件";
        String title = "待签署文件：" + fileName;
        if (existing != null) {
            ensureTodoForUnsignedDetail(existing, title);
            return;
        }
        HotSignFileDetail detail = new HotSignFileDetail();
        detail.setCompanyId(doc.getCompanyId());
        detail.setIssueFileId(doc.getId());
        detail.setStaffId(staffId);
        detail.setStaffName(staffName);
        detail.setStaffType(staffType);
        detail.setSignStatus(0L);
        detail.setIsArchived(0L);
        detail.setIsDeleted(0L);
        signFileDetailMapper.insert(detail);
        if (detail.getId() != null) {
            flowService.pushDirectTodo("SIGN_FILE", String.valueOf(detail.getId()), title, detail.getCompanyId(), staffId);
        }
    }

    private void ensureTodoForUnsignedDetail(HotSignFileDetail detail, String title) {
        if (detail == null || detail.getId() == null || StringUtils.isBlank(detail.getStaffId())) {
            return;
        }
        if (detail.getSignStatus() != null && detail.getSignStatus() == 1L) {
            return;
        }
        String taskId = flowService.getTaskIdByBusinessId("SIGN_FILE", String.valueOf(detail.getId()), detail.getStaffId());
        if (StringUtils.isBlank(taskId)) {
            flowService.pushDirectTodo("SIGN_FILE", String.valueOf(detail.getId()), title, detail.getCompanyId(), detail.getStaffId());
        }
    }

    private void appendIssuePersonId(HotNoticeSignDocument doc, String staffId) {
        if (doc == null || doc.getId() == null || StringUtils.isBlank(staffId)) {
            return;
        }
        Set<String> personIds = parsePersonIds(doc.getIssuePersonIds());
        if (!personIds.add(staffId)) {
            return;
        }
        HotNoticeSignDocument update = new HotNoticeSignDocument();
        update.setId(doc.getId());
        update.setIssuePersonIds(String.join(",", personIds));
        baseMapper.updateById(update);
        doc.setIssuePersonIds(update.getIssuePersonIds());
    }

    private String resolveTemplateNameSnapshot(Long templateId) {
        if (templateId == null) {
            return null;
        }
        HotDispatchTemplate template = dispatchTemplateMapper.selectById(templateId);
        if (template == null) {
            throw new ServiceException("下发模板不存在");
        }
        return template.getTemplateName();
    }

    private Long resolveSourceCompanyId() {
        if (LoginHelper.isSuperAdmin()) {
            return 1L;
        }
        Long companyId = LoginHelper.getCompanyId();
        if (companyId == null) {
            throw new ServiceException("当前登录用户无公司信息");
        }
        return companyId;
    }

    private Set<String> parsePersonIds(String ids) {
        Set<String> set = new LinkedHashSet<>();
        if (StringUtils.isBlank(ids)) {
            return set;
        }
        String[] parts = ids.split(",");
        for (String part : parts) {
            if (part == null) {
                continue;
            }
            String v = part.trim();
            if (StringUtils.isNotBlank(v)) {
                set.add(v);
            }
        }
        return set;
    }

    private Set<String> findInvalidPersonIds(Set<String> personIds) {
        if (personIds == null || personIds.isEmpty()) {
            return Collections.emptySet();
        }
        Set<String> valid = findValidPersonIds(personIds);
        Set<String> invalid = new LinkedHashSet<>(personIds);
        invalid.removeAll(valid);
        return invalid;
    }

    private Set<String> findValidPersonIds(Set<String> personIds) {
        Set<String> rawIds = personIds.stream()
                .filter(StringUtils::isNotBlank)
                .map(String::trim)
                .distinct()
                .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
        if (rawIds.isEmpty()) {
            return Collections.emptySet();
        }

        List<Long> managerIds = rawIds.stream()
                .filter(v -> v.matches("\\d+"))
                .map(Long::valueOf)
                .distinct()
                .toList();

        Set<String> valid = new HashSet<>(rawIds.size());

        if (!managerIds.isEmpty()) {
            List<HotCompanySafetyManager> managers = safetyManagerMapper.selectList(
                    Wrappers.<HotCompanySafetyManager>lambdaQuery()
                            .in(HotCompanySafetyManager::getId, managerIds)
                            .eq(HotCompanySafetyManager::getIsDeleted, 0L)
                            .eq(HotCompanySafetyManager::getIsResigned, 0L)
                            .eq(HotCompanySafetyManager::getStatus, 1L)
            );
            if (managers != null) {
                for (HotCompanySafetyManager m : managers) {
                    if (m != null && m.getId() != null) {
                        valid.add(String.valueOf(m.getId()));
                    }
                }
            }
        }

        List<HotDriver> drivers = driverMapper.selectList(
                Wrappers.<HotDriver>lambdaQuery()
                        .in(HotDriver::getId, rawIds)
                        .eq(HotDriver::getIsDeleted, 0L)
                        .eq(HotDriver::getStatus, 1L)
                        .eq(HotDriver::getAuditStatus, 1)
        );
        if (drivers != null) {
            for (HotDriver d : drivers) {
                if (d != null && d.getId() != null) {
                    valid.add(String.valueOf(d.getId()));
                }
            }
        }

        return valid;
    }

    private Set<String> normalizePersonIds(Set<String> oldPersonIds, Set<String> requestedPersonIds) {
        Set<String> invalidOldPersonIds = findInvalidPersonIds(oldPersonIds);
        if (invalidOldPersonIds.isEmpty()) {
            return requestedPersonIds;
        }
        Set<String> merged = new LinkedHashSet<>(requestedPersonIds);
        merged.addAll(invalidOldPersonIds);
        return merged;
    }

    private void validateRemovedPersons(HotNoticeSignDocument old, Set<String> oldPersonIds, Set<String> finalPersonIds) {
        if (old == null || oldPersonIds == null || finalPersonIds == null || oldPersonIds.equals(finalPersonIds)) {
            return;
        }
        Set<String> removedIds = new HashSet<>(oldPersonIds);
        removedIds.removeAll(finalPersonIds);
        if (removedIds.isEmpty()) {
            return;
        }
        List<HotSignFileDetail> existingDetails = signFileDetailMapper.selectList(
                Wrappers.<HotSignFileDetail>lambdaQuery()
                        .eq(HotSignFileDetail::getIssueFileId, old.getId())
                        .eq(HotSignFileDetail::getIsDeleted, 0)
                        .in(HotSignFileDetail::getStaffId, removedIds)
        );
        if (existingDetails == null || existingDetails.isEmpty()) {
            return;
        }
        Set<String> blockedNames = new LinkedHashSet<>();
        for (HotSignFileDetail detail : existingDetails) {
            if (detail == null) {
                continue;
            }
            String name = StringUtils.isNotBlank(detail.getStaffName()) ? detail.getStaffName() : "未知人员";
            blockedNames.add(name);
        }
        if (!blockedNames.isEmpty()) {
            throw new ServiceException("已下发人员不能被移出: " + String.join(",", blockedNames));
        }
    }

    private void issueNewDetailsAndTodos(HotNoticeSignDocument old, HotNoticeSignDocument update, Set<String> oldPersonIds, Set<String> finalPersonIds) {
        if (old == null || update == null || update.getId() == null || update.getCompanyId() == null) {
            return;
        }
        Set<String> validFinalIds = findValidPersonIds(finalPersonIds);
        if (validFinalIds.isEmpty()) {
            return;
        }
        Set<String> addedValidIds = new LinkedHashSet<>(validFinalIds);
        if (oldPersonIds != null) {
            addedValidIds.removeAll(oldPersonIds);
        }
        if (addedValidIds.isEmpty()) {
            return;
        }

        Map<String, String> idToName = resolvePersonNames(addedValidIds);
        Map<String, Long> idToStaffType = resolvePersonTypes(addedValidIds);
        List<HotSignFileDetail> existing = signFileDetailMapper.selectList(
                Wrappers.<HotSignFileDetail>lambdaQuery()
                        .eq(HotSignFileDetail::getIssueFileId, update.getId())
                        .eq(HotSignFileDetail::getIsDeleted, 0)
                        .in(HotSignFileDetail::getStaffId, addedValidIds)
        );
        Set<String> existingStaffIds = new HashSet<>();
        if (existing != null) {
            for (HotSignFileDetail d : existing) {
                if (d != null && StringUtils.isNotBlank(d.getStaffId())) {
                    existingStaffIds.add(d.getStaffId());
                }
            }
        }

        String fileName = StringUtils.isNotBlank(update.getFileName()) ? update.getFileName() : old.getFileName();
        String title = "待签署文件：" + (StringUtils.isNotBlank(fileName) ? fileName : "未知文件");

        if (existing != null) {
            for (HotSignFileDetail d : existing) {
                if (d == null || d.getId() == null || StringUtils.isBlank(d.getStaffId())) {
                    continue;
                }
                if (d.getSignStatus() != null && d.getSignStatus() == 1L) {
                    continue;
                }
                String taskId = flowService.getTaskIdByBusinessId("SIGN_FILE", String.valueOf(d.getId()), d.getStaffId());
                if (StringUtils.isBlank(taskId)) {
                    flowService.pushDirectTodo("SIGN_FILE", String.valueOf(d.getId()), title, d.getCompanyId(), d.getStaffId());
                }
            }
        }

        for (String staffId : addedValidIds) {
            if (StringUtils.isBlank(staffId) || existingStaffIds.contains(staffId)) {
                continue;
            }
            HotSignFileDetail detail = new HotSignFileDetail();
            detail.setCompanyId(update.getCompanyId());
            detail.setIssueFileId(update.getId());
            detail.setStaffId(staffId);
            detail.setStaffName(idToName.getOrDefault(staffId, null));
            detail.setStaffType(idToStaffType.getOrDefault(staffId, STAFF_TYPE_DRIVER_PRACTITIONER));
            detail.setSignStatus(0L);
            detail.setIsArchived(0L);
            detail.setIsDeleted(0L);
            signFileDetailMapper.insert(detail);

            if (detail.getId() != null) {
                flowService.pushDirectTodo("SIGN_FILE", String.valueOf(detail.getId()), title, detail.getCompanyId(), staffId);
            }
        }
    }

    private Map<String, String> resolvePersonNames(Set<String> personIds) {
        Set<String> rawIds = personIds.stream()
                .filter(StringUtils::isNotBlank)
                .map(String::trim)
                .distinct()
                .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
        if (rawIds.isEmpty()) {
            return Collections.emptyMap();
        }

        Map<String, String> map = new HashMap<>();

        List<Long> managerIds = rawIds.stream()
                .filter(v -> v.matches("\\d+"))
                .map(Long::valueOf)
                .distinct()
                .toList();
        if (!managerIds.isEmpty()) {
            List<HotCompanySafetyManager> managers = safetyManagerMapper.selectList(
                    Wrappers.<HotCompanySafetyManager>lambdaQuery()
                            .in(HotCompanySafetyManager::getId, managerIds)
                            .eq(HotCompanySafetyManager::getIsDeleted, 0L)
            );
            if (managers != null) {
                for (HotCompanySafetyManager m : managers) {
                    if (m == null || m.getId() == null || StringUtils.isBlank(m.getName())) {
                        continue;
                    }
                    map.putIfAbsent(String.valueOf(m.getId()), m.getName());
                }
            }
        }

        List<HotDriver> drivers = driverMapper.selectList(
                Wrappers.<HotDriver>lambdaQuery()
                        .in(HotDriver::getId, rawIds)
                        .eq(HotDriver::getIsDeleted, 0L)
        );
        if (drivers != null) {
            for (HotDriver d : drivers) {
                if (d == null || d.getId() == null || StringUtils.isBlank(d.getName())) {
                    continue;
                }
                map.putIfAbsent(String.valueOf(d.getId()), d.getName());
            }
        }

        return map;
    }

    private Map<String, Long> resolvePersonTypes(Set<String> personIds) {
        Set<String> rawIds = personIds.stream()
                .filter(StringUtils::isNotBlank)
                .map(String::trim)
                .collect(java.util.stream.Collectors.toCollection(LinkedHashSet::new));
        if (rawIds.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, Long> typeMap = new HashMap<>();
        List<Long> managerIds = rawIds.stream()
                .filter(v -> v.matches("\\d+"))
                .map(Long::valueOf)
                .distinct()
                .toList();
        if (!managerIds.isEmpty()) {
            List<HotCompanySafetyManager> managers = safetyManagerMapper.selectList(
                    Wrappers.<HotCompanySafetyManager>lambdaQuery()
                            .in(HotCompanySafetyManager::getId, managerIds)
                            .eq(HotCompanySafetyManager::getIsDeleted, 0L)
            );
            if (managers != null) {
                for (HotCompanySafetyManager m : managers) {
                    if (m != null && m.getId() != null) {
                        typeMap.put(String.valueOf(m.getId()), STAFF_TYPE_MANAGER);
                    }
                }
            }
        }
        List<HotDriver> drivers = driverMapper.selectList(
                Wrappers.<HotDriver>lambdaQuery()
                        .in(HotDriver::getId, rawIds)
                        .eq(HotDriver::getIsDeleted, 0L)
        );
        if (drivers != null) {
            for (HotDriver d : drivers) {
                if (d != null && d.getId() != null) {
                    typeMap.putIfAbsent(d.getId(), mapDriverStaffType(d.getPersonType()));
                }
            }
        }
        return typeMap;
    }

    private long mapDriverStaffType(String personType) {
        if (isDriverOrEscortPersonType(personType)) {
            return STAFF_TYPE_DRIVER;
        }
        if (StringUtils.isBlank(personType)) {
            return STAFF_TYPE_DRIVER_PRACTITIONER;
        }
        return STAFF_TYPE_DRIVER_PRACTITIONER;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HotNoticeSignDocument entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除签订文件信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
}
