package jnpf.personnels.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jnpf.base.ActionResult;
import jnpf.model.enums.GrowthLogEnum;
import jnpf.model.personnels.dto.staff.employment.FtbPersonnelsEmployApplyListDto;
import jnpf.model.personnels.dto.staff.employment.FtbPersonnelsMoveLogVO;
import jnpf.model.personnels.dto.staff.employment.FtbPersonnelsRegularVO;
import jnpf.model.personnels.dto.staff.employment.FtbPersonnelsTurnoverLogVO;
import jnpf.model.personnels.dto.staff.roster.StaffDepartDto;
import jnpf.model.personnels.dto.staff.roster.StaffPromotionDto;
import jnpf.model.personnels.dto.staff.roster.StaffRegularDto;
import jnpf.model.personnels.dto.staff.transfer.TransferGrowthLogDto;
import jnpf.model.personnels.po.FtbPersonnelsSecondmentManagement;
import jnpf.model.personnels.po.FtbPersonnelsStaffGrowthLog;
import jnpf.model.personnels.po.FtbPersonnelsStaffRoster;
import jnpf.model.personnels.po.FtbPersonnelsTransferManage;
import jnpf.model.personnels.vo.roster.FtbHomePageRewardVO;
import jnpf.model.personnels.vo.roster.FtbPersonnelsChangeInfoVO;
import jnpf.model.personnels.vo.secondment.FtbPersonnelsSecondRecordVO;
import jnpf.permission.V2UserApi;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.mapper.FtbPersonnelsStaffHomePageMapper;
import jnpf.personnels.mapper.FtbPersonnelsStaffRosterMapper;
import jnpf.personnels.service.FtbPersonnelsSecondmentManagementService;
import jnpf.personnels.service.FtbPersonnelsStaffGrowthLogService;
import jnpf.personnels.service.FtbPersonnelsStaffHomePageService;
import jnpf.personnels.service.FtbPersonnelsTransferManageService;
import jnpf.util.UserProvider;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class FtbPersonnelsStaffHomePageServiceImpl implements FtbPersonnelsStaffHomePageService {

    @Resource
    private FtbPersonnelsStaffRosterMapper ftbPersonnelsStaffRosterMapper;
    @Resource
    private FtbPersonnelsStaffHomePageMapper ftbPersonnelsStaffHomePageMapper;
    @Resource
    private V2UserApi v2UserApi;
    @Resource
    private FtbPersonnelsStaffGrowthLogService staffGrowthLogService;
    @Resource
    FtbPersonnelsTransferManageService transferManageService;
    @Resource
    private FtbPersonnelsSecondmentManagementService ftbPersonnelsSecondmentService;

    @Override
    public String checkPersonalCommitments(String id) {
        LambdaQueryWrapper<FtbPersonnelsStaffRoster> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbPersonnelsStaffRoster::getRegisterImg);
        queryWrapper.eq(FtbPersonnelsStaffRoster::getEnabledMark, 0);
        queryWrapper.eq(FtbPersonnelsStaffRoster::getUserId, id);
        FtbPersonnelsStaffRoster ftbPersonnelsStaffRoster = ftbPersonnelsStaffRosterMapper.selectOne(queryWrapper);
        if (Objects.nonNull(ftbPersonnelsStaffRoster)) {
            return ftbPersonnelsStaffRoster.getRegisterImg();
        }
        return "";
    }

    @Override
    public List<FtbHomePageRewardVO> getRewardList(String id) {
        List<FtbHomePageRewardVO> rewardList = ftbPersonnelsStaffHomePageMapper.getRewardList(id);
        operatorHandling(rewardList);
        return rewardList;
    }

    @Override
    public List<FtbHomePageRewardVO> donationRecords(String id) {
        List<FtbHomePageRewardVO> ftbHomePageRewardVOS = ftbPersonnelsStaffHomePageMapper.donationRecords(id);
        operatorHandling(ftbHomePageRewardVOS);
        return ftbHomePageRewardVOS;
    }

    @Override
    public Map<String, FtbPersonnelsChangeInfoVO> getBatchPersonnelChangeInfo(List<String> userIds) {
        if (CollUtil.isEmpty(userIds)) {
            return new HashMap<>();
        }

        // 1. 批量查询所有相关 growth_log
        LambdaQueryWrapper<FtbPersonnelsStaffGrowthLog> logWrapper = Wrappers.lambdaQuery();
        logWrapper.in(FtbPersonnelsStaffGrowthLog::getUserId, userIds);
        // 可选：只查需要的类型，减少数据量
        // logWrapper.in(FtbPersonnelsStaffGrowthLog::getGrowthType, 需要的类型列表);
        List<FtbPersonnelsStaffGrowthLog> allLogs = staffGrowthLogService.list(logWrapper);

        // 2. 批量查询所有相关的 transfer_manage
        LambdaQueryWrapper<FtbPersonnelsTransferManage> transferWrapper = Wrappers.lambdaQuery();
        transferWrapper.in(FtbPersonnelsTransferManage::getUserId, userIds);
        transferWrapper.in(FtbPersonnelsTransferManage::getProcessingStatus, List.of(6, 2));
        transferWrapper.eq(FtbPersonnelsTransferManage::getImplementType, 1);
        List<FtbPersonnelsTransferManage> allTransfers = transferManageService.list(transferWrapper);

        // 3. 批量查询所有相关的 secondment
        LambdaQueryWrapper<FtbPersonnelsSecondmentManagement> secondWrapper = Wrappers.lambdaQuery();
        secondWrapper.in(FtbPersonnelsSecondmentManagement::getUserId, userIds);
        secondWrapper.in(FtbPersonnelsSecondmentManagement::getTransferStatus, 6, 2);
        List<FtbPersonnelsSecondmentManagement> allSecondments = ftbPersonnelsSecondmentService.list(secondWrapper);

        LambdaQueryWrapper<FtbPersonnelsStaffRoster> staffRosterLambdaQueryWrapper = Wrappers.lambdaQuery();
        staffRosterLambdaQueryWrapper.in(FtbPersonnelsStaffRoster::getUserId, userIds);
        List<FtbPersonnelsStaffRoster> selectList = ftbPersonnelsStaffRosterMapper.selectList(staffRosterLambdaQueryWrapper);
        Map<String, FtbPersonnelsStaffRoster> staffRosterMap = selectList
                .stream()
                .collect(Collectors.toMap(FtbPersonnelsStaffRoster::getUserId, Function.identity()));
        // 4. 收集所有涉及到的 userId（包括 creatorUserId）
        Set<String> allRelatedUserIds = new HashSet<>(userIds);

        allLogs.forEach(log -> {
            allRelatedUserIds.add(log.getCreatorUserId());
            allRelatedUserIds.add(log.getUserId());
        });
        allTransfers.forEach(t -> {
            allRelatedUserIds.add(t.getCreatorUserId());
            if (t.getLastModifyUserId() != null) {
                allRelatedUserIds.add(t.getLastModifyUserId());
            }
        });
        allSecondments.forEach(s -> allRelatedUserIds.add(s.getCreatorUserId()));

        // 5. 批量获取用户名
        ActionResult<List<UserBoundVO>> boundResult = v2UserApi.getUserPrimaryBoundBatch(
                new ArrayList<>(allRelatedUserIds), UserProvider.getUser().getTenantId());

        Map<String, String> userNameMap = new HashMap<>();
        if (boundResult.getData() != null) {
            userNameMap = boundResult.getData().stream()
                    .collect(Collectors.toMap(UserBoundVO::getId, UserBoundVO::getUserName, (a, b) -> a));
        }

        // 6. 按 userId 分组 growth log
        Map<String, List<FtbPersonnelsStaffGrowthLog>> logByUser = allLogs.stream()
                .collect(Collectors.groupingBy(FtbPersonnelsStaffGrowthLog::getUserId));

        // 7. 按 userId 分组 transfer
        Map<String, List<FtbPersonnelsTransferManage>> transferByUser = allTransfers.stream()
                .collect(Collectors.groupingBy(FtbPersonnelsTransferManage::getUserId));

        // 8. 按 userId 分组 secondment
        Map<String, List<FtbPersonnelsSecondmentManagement>> secondByUser = allSecondments.stream()
                .collect(Collectors.groupingBy(FtbPersonnelsSecondmentManagement::getUserId));

        // 9. 按 userId 批量构建 VO
        Map<String, FtbPersonnelsChangeInfoVO> result = new LinkedHashMap<>();

        for (String uid : userIds) {
            FtbPersonnelsChangeInfoVO vo = new FtbPersonnelsChangeInfoVO();

            // 入职
            vo.setOnboarding(convertToEmployApplyList(logByUser.getOrDefault(uid, Collections.emptyList()), userNameMap));

            // 转正
            vo.setRegularization(convertToRegularList(logByUser.getOrDefault(uid, Collections.emptyList()), userNameMap));

            // 调动（包含旧 growth_log + 新 transfer_manage）
            vo.setMobilize(convertToMoveLogList(
                    logByUser.getOrDefault(uid, Collections.emptyList()),
                    transferByUser.getOrDefault(uid, Collections.emptyList()),
                    userNameMap));

            // 借调
            vo.setSeconded(convertToSecondRecordList(
                    secondByUser.getOrDefault(uid, Collections.emptyList()),
                    userNameMap,
                    staffRosterMap
                    ));

            // 离职
            vo.setTurnover(convertToTurnoverList(logByUser.getOrDefault(uid, Collections.emptyList()), userNameMap));

            result.put(uid, vo);
        }

        return result;
    }

    private List<FtbPersonnelsEmployApplyListDto> convertToEmployApplyList(
            List<FtbPersonnelsStaffGrowthLog> logs, Map<String, String> nameMap) {
        return logs.stream()
                .filter(log -> log.getGrowthType() == 0 || log.getGrowthType() == 3)
                .map(log -> {
                    FtbPersonnelsEmployApplyListDto dto = FtbPersonnelsEmployApplyListDto.covert(log);
                    dto.setWorkName(nameMap.getOrDefault(log.getUserId(), "-"));
                    dto.setOperator(nameMap.getOrDefault(log.getCreatorUserId(), "-"));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    private List<FtbPersonnelsRegularVO> convertToRegularList(
            List<FtbPersonnelsStaffGrowthLog> logs,
            Map<String, String> userNameMap) {

        return logs.stream()
                .filter(log -> Objects.equals(log.getGrowthType(), GrowthLogEnum.BECOME_REGULAR_WORKER.getCode()))
                .map(log -> {
                    StaffRegularDto dto = JSONUtil.toBean(log.getDetail(), StaffRegularDto.class);

                    FtbPersonnelsRegularVO vo = FtbPersonnelsRegularVO.covert(dto);
                    vo.setName(userNameMap.getOrDefault(log.getUserId(), "-"));
                    vo.setProcessingDate(log.getCreatorTime());
                    vo.setEmployeeID(log.getEmployeeId());
                    vo.setOperator(userNameMap.getOrDefault(log.getCreatorUserId(), "-"));

                    return vo;
                })
                .collect(Collectors.toList());
    }

    private List<FtbPersonnelsTurnoverLogVO> convertToTurnoverList(
            List<FtbPersonnelsStaffGrowthLog> logs,
            Map<String, String> userNameMap) {

        return logs.stream()
                .filter(log -> Objects.equals(log.getGrowthType(), GrowthLogEnum.DEPART.getCode()) ||
                        Objects.equals(log.getGrowthType(), GrowthLogEnum.PRE_TRAIL.getCode()))
                .map(log -> {
                    FtbPersonnelsTurnoverLogVO vo = new FtbPersonnelsTurnoverLogVO();

                    if (StrUtil.isNotBlank(log.getDetail()) && !"[]".equals(log.getDetail())) {
                        StaffDepartDto dto;
                        try {
                            // 优先尝试数组格式（兼容旧数据）
                            List<StaffDepartDto> list = JSONArray.parseArray(log.getDetail(), StaffDepartDto.class);
                            dto = CollUtil.isNotEmpty(list) ? list.get(0) : null;
                        } catch (Exception e) {
                            // 再尝试单个对象
                            dto = JSONObject.parseObject(log.getDetail(), StaffDepartDto.class);
                        }

                        if (dto != null) {
                            vo = FtbPersonnelsTurnoverLogVO.covert(dto);
                        }
                    }

                    vo.setName(userNameMap.getOrDefault(log.getUserId(), "-"));
                    vo.setProcessingDate(log.getChangeDate() != null ? log.getChangeDate() : log.getCreatorTime());
                    vo.setEmployeeID(log.getEmployeeId());
                    vo.setOperator(userNameMap.getOrDefault(log.getCreatorUserId(), "-"));

                    return vo;
                })
                .collect(Collectors.toList());
    }

    private List<FtbPersonnelsSecondRecordVO> convertToSecondRecordList(
            List<FtbPersonnelsSecondmentManagement> secondments,
            Map<String, String> userNameMap,
            Map<String, FtbPersonnelsStaffRoster> rosterMap
    ) {
        return secondments.stream()
                .map(item -> {
                    FtbPersonnelsSecondRecordVO vo = FtbPersonnelsSecondRecordVO.covert(item);
                    vo.setCreatorUserName(userNameMap.getOrDefault(item.getCreatorUserId(), "-"));
                    // 如果有 rosterMap，可以这样取
                    FtbPersonnelsStaffRoster roster = rosterMap.getOrDefault(item.getUserId(), null);
                    vo.setEmployeeId(roster != null ? roster.getSystemWokerId() : "-");
                    vo.setUserName(roster != null ? roster.getName() : "-");
                    // 如果没有 rosterMap，保持原逻辑用 "-" 占位
                    vo.setEmployeeId("-");
                    vo.setUserName("-");

                    return vo;
                })
                .collect(Collectors.toList());
    }

    private List<FtbPersonnelsMoveLogVO> convertToMoveLogList(
            List<FtbPersonnelsStaffGrowthLog> growthLogs,
            List<FtbPersonnelsTransferManage> transferManages,
            Map<String, String> userNameMap) {

        List<FtbPersonnelsMoveLogVO> result = new ArrayList<>();

        // 第一部分：来自旧的 growth_log（晋升 + 调岗）
        growthLogs.stream()
                .filter(log -> Objects.equals(log.getGrowthType(), GrowthLogEnum.promotion.getCode()) ||
                        Objects.equals(log.getGrowthType(), GrowthLogEnum.TRANSFER_POSITION.getCode()))
                .forEach(log -> {
                    FtbPersonnelsMoveLogVO vo = new FtbPersonnelsMoveLogVO();

                    if (Objects.equals(log.getGrowthType(), GrowthLogEnum.promotion.getCode())) {
                        StaffPromotionDto dto = JSONUtil.toBean(log.getDetail(), StaffPromotionDto.class);
                        vo = FtbPersonnelsMoveLogVO.covert(dto);           // 假设有这个方法
                    } else if (Objects.equals(log.getGrowthType(), GrowthLogEnum.TRANSFER_POSITION.getCode())) {
                        TransferGrowthLogDto dto = JSONUtil.toBean(log.getDetail(), TransferGrowthLogDto.class);
                        vo = FtbPersonnelsMoveLogVO.covertTransfer(dto);   // 假设有这个方法
                    }

                    vo.setName(userNameMap.getOrDefault(log.getUserId(), "-"));
                    vo.setOperator(userNameMap.getOrDefault(log.getCreatorUserId(), "-"));
                    vo.setProcessingDate(log.getCreatorTime());
                    vo.setEmployeeID(log.getEmployeeId());

                    // 可选：设置 type
                    vo.setType(Objects.equals(log.getGrowthType(), GrowthLogEnum.promotion.getCode()) ? "晋升" : "调岗");

                    result.add(vo);
                });

        // 第二部分：来自新的 transfer_manage（状态为已实施或已通过）
        transferManages.forEach(item -> {
            FtbPersonnelsMoveLogVO vo = FtbPersonnelsMoveLogVO.covertPromotion(item);  // 假设有这个方法

            vo.setName(userNameMap.getOrDefault(item.getUserId(), "-"));

            // 类型判断（新字段 state）
            Integer state = item.getState();
            String type = "未知异动";
            if (state != null) {
                switch (state) {
                    case 0:
                        type = "调岗";
                        break;
                    case 1:
                        type = "晋升";
                        break;
                    case 2:
                        type = "降职";
                        break;
                    case 3:
                        type = "调店";
                        break;
                }
            }
            vo.setType(type);

            // 操作人逻辑（已实施用 creator，已通过用 lastModify）
            String operatorId = (item.getProcessingStatus() == 6 && item.getCreatorUserId() != null)
                    ? item.getCreatorUserId()
                    : (item.getProcessingStatus() == 2 && item.getLastModifyUserId() != null)
                    ? item.getLastModifyUserId()
                    : null;

            vo.setOperator(userNameMap.getOrDefault(operatorId, "-"));

            vo.setProcessingDate(item.getCreatorTime()); // 或用其他合适的时间字段
            vo.setEmployeeID("-"); // 如果有 employeeId 字段可补充

            result.add(vo);
        });

        // 可选：按时间排序（如果前端需要按时间倒序）
        result.sort(Comparator.comparing(
                FtbPersonnelsMoveLogVO::getProcessingDate,
                Comparator.nullsLast(Comparator.reverseOrder())
        ));

        return result;
    }

    private void operatorHandling(List<FtbHomePageRewardVO> rewardList) {
        if (rewardList.isEmpty()) {
            return;
        }
        List<String> userIds = rewardList.stream().map(FtbHomePageRewardVO::getOperator).collect(Collectors.toList());
        ActionResult<List<UserBoundVO>> userPrimaryBoundBatch = v2UserApi.getUserPrimaryBoundBatch(userIds, null);
        if (userPrimaryBoundBatch == null || CollUtil.isEmpty(userPrimaryBoundBatch.getData())) {
            return;
        }
        Map<String, List<UserBoundVO>> map = userPrimaryBoundBatch.getData().stream().collect(Collectors.groupingBy(UserBoundVO::getId));
        for (FtbHomePageRewardVO ftbHomePageRewardVO : rewardList) {
            List<UserBoundVO> orDefault = map.getOrDefault(ftbHomePageRewardVO.getOperator(), null);
            if (CollUtil.isEmpty(orDefault)) {
                ftbHomePageRewardVO.setOperator("--");
                continue;
            }
            ftbHomePageRewardVO.setOperator(orDefault.get(0).getUserName());
        }
    }
}
