package jnpf.attendance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jnpf.attendance.mapper.AttendanceCustomizeTableMapper;
import jnpf.attendance.service.AttendanceCustomizeTableService;
import jnpf.attendance.service.AttendanceLeaveTypeService;
import jnpf.base.service.SuperServiceImpl;
import jnpf.entity.AttendanceCustomizeTable;
import jnpf.entity.attendance.AttendanceLeaveType;
import jnpf.model.attendance.model.LeaveTypeJsonHead;
import jnpf.model.attendance.vo.attendance.AttendanceCustomizeTableVo;
import jnpf.model.attendance.vo.attendance.CustomizeTableUpdateVo;
import jnpf.util.JsonUtil;
import jnpf.util.StringUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSON.parseArray;

/**
 * <p>
 * 考勤-自定义报表设置 服务实现类
 * </p>
 *
 * @author ahua
 * @since 2024-09-03
 */
@Service
public class AttendanceCustomizeTableServiceImpl extends SuperServiceImpl<AttendanceCustomizeTableMapper, AttendanceCustomizeTable> implements AttendanceCustomizeTableService {
    @Resource
    private AttendanceLeaveTypeService attendanceLeaveTypeService;

    @Override
    @Transactional
    public List<AttendanceCustomizeTableVo> findList(String keyword, Integer status, Integer type) {
        List<AttendanceCustomizeTable> list = lambdaQuery().like(StringUtil.isNotEmpty(keyword), AttendanceCustomizeTable::getFieldName, keyword).eq(Objects.nonNull(status), AttendanceCustomizeTable::getStatus, status).eq(AttendanceCustomizeTable::getType, type).orderByAsc(AttendanceCustomizeTable::getSort).list();
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        // 查询自定义假期表头
        AttendanceCustomizeTable customLeaveJson = list.stream().filter(customizeTable -> "customLeaveJson".equals(customizeTable.getField())).findFirst().orElse(null);
        if (Objects.nonNull(customLeaveJson)) {
            list.removeIf(customizeTable -> "customLeaveJson".equals(customizeTable.getField()));
        }
        List<AttendanceCustomizeTableVo> tableVos = BeanUtil.copyToList(list, AttendanceCustomizeTableVo.class);
        // 判断是否存在自定义请假Json数据
        Map<String, LeaveTypeJsonHead> typeJsonDataMap = new HashMap<>();
        if (customLeaveJson != null && StringUtil.isNotEmpty(customLeaveJson.getCustomLeaveJson())) {
            List<LeaveTypeJsonHead> typeJsonDataList = parseArray(customLeaveJson.getCustomLeaveJson(), LeaveTypeJsonHead.class);
            Optional.ofNullable(typeJsonDataList).ifPresent(typeJsonDataList1 -> typeJsonDataList1.forEach(typeJsonData -> typeJsonDataMap.put(typeJsonData.getField(), typeJsonData)));
        }
        // 实时查询自定义请见类型
        List<AttendanceLeaveType> leaveRulesLiat = attendanceLeaveTypeService.list(new LambdaQueryWrapper<AttendanceLeaveType>()
                .ne(AttendanceLeaveType::getBuiltIn, 1)
                .isNotNull(AttendanceLeaveType::getDeleteMark)
                .orderByAsc(AttendanceLeaveType::getCreatorTime));
        if (CollUtil.isEmpty(leaveRulesLiat)) {
            return tableVos;
        }
        // 封装所有请假类型数据
        List<LeaveTypeJsonHead> typeJsonDataList = CollUtil.newArrayList();
        // 获取最大排序
        int maxSort = tableVos.stream().mapToInt(AttendanceCustomizeTableVo::getSort).max().orElse(0);
        int maxLeaveSort = typeJsonDataMap.values().stream().mapToInt(LeaveTypeJsonHead::getSort).max().orElse(0);
        AtomicInteger rank = new AtomicInteger(Math.max(maxSort, maxLeaveSort));
        AtomicBoolean isAdd = new AtomicBoolean(false);
        leaveRulesLiat.forEach(leaveRules -> {
            LeaveTypeJsonHead typeJsonData;
            if (typeJsonDataMap.containsKey(leaveRules.getId())) {
                typeJsonData = typeJsonDataMap.get(leaveRules.getId());
                if (!leaveRules.getName().equals(typeJsonData.getFieldName()) || !leaveRules.getDeleteMark().equals(typeJsonData.getShow())) {
                    isAdd.set(true);
                }
                typeJsonData.setShow(leaveRules.getDeleteMark());
                typeJsonData.setDeleteTime(leaveRules.getDeleteTime());
                typeJsonData.setFieldName(leaveRules.getName());
                typeJsonData.setHeadName(leaveRules.getName());
            } else {
                isAdd.set(true);
                typeJsonData = LeaveTypeJsonHead.builder()
                        .field(leaveRules.getId())
                        .customLeave(1)
                        .fieldName(leaveRules.getName())
                        .headName(leaveRules.getName())
                        .width(120)
                        .status(1)
                        .show(leaveRules.getDeleteMark())
                        .deleteTime(leaveRules.getDeleteTime())
                        .sort(rank.getAndIncrement())
                        .build();
            }
            typeJsonDataList.add(typeJsonData);
        });
        // 是否有新增假类型，或者变更请假名称
        if (isAdd.get() && Objects.nonNull(customLeaveJson)) {
            customLeaveJson.setCustomLeaveJson(JSON.toJSONString(typeJsonDataList));
            list.add(customLeaveJson);
            updateBatchById(list);
        }
        if (Objects.nonNull(customLeaveJson)) {
            // 重新生成序号
            AtomicInteger index = new AtomicInteger(typeJsonDataList.stream().mapToInt(LeaveTypeJsonHead::getSort).min().orElse(0));
            typeJsonDataList.sort(Comparator.comparingInt(LeaveTypeJsonHead::getShow));
            typeJsonDataList.forEach(typeJsonData -> typeJsonData.setSort(index.getAndIncrement()));
            customLeaveJson.setCustomLeaveJson(JSON.toJSONString(typeJsonDataList));
            updateById(customLeaveJson);
        }
        if (CollUtil.isNotEmpty(typeJsonDataList)) {
            tableVos.addAll(typeJsonDataList.stream().map(typeJsonData -> AttendanceCustomizeTableVo.builder()
                    .id(typeJsonData.getField())
                    .field(typeJsonData.getField())
                    .customLeave(1)
                    .sort(typeJsonData.getSort())
                    .fieldName(typeJsonData.getFieldName())
                    .headName(typeJsonData.getHeadName())
                    .status(typeJsonData.getStatus())
                    .show(typeJsonData.getShow())
                    .width(typeJsonData.getWidth())
                    .deleteTime(typeJsonData.getDeleteTime())
                    .build()).collect(Collectors.toList()));
        }
        tableVos.sort(Comparator.comparingInt(AttendanceCustomizeTableVo::getSort));
        return tableVos;
    }

    @Override
    @Transactional
    public void update(CustomizeTableUpdateVo tableVos) {
        Assert.notEmpty(tableVos.getTableVos(), "当前变更数据为空");
        // 获取自定义假字段
        List<AttendanceCustomizeTableVo> customLeaveTableVos = tableVos.getTableVos().stream().filter(tableVo -> tableVo.getCustomLeave().equals(1)).collect(Collectors.toList());
        // 转化为自定义请假类型
        List<LeaveTypeJsonHead> typeJsonDataList = CollUtil.isNotEmpty(customLeaveTableVos) ? JsonUtil.getJsonToList(customLeaveTableVos, LeaveTypeJsonHead.class) : CollUtil.newArrayList();
        // 移除掉自定义假字段
        tableVos.getTableVos().removeIf(tableVo -> tableVo.getCustomLeave().equals(1));
        //转化为数据库实体
        List<AttendanceCustomizeTable> updateDataList = tableVos.getTableVos().stream().map(tableVo -> BeanUtil.toBean(tableVo, AttendanceCustomizeTable.class)).collect(Collectors.toList());
        // 获取自定义假期Json字段
        AttendanceCustomizeTable customLeaveJsonField = lambdaQuery().eq(AttendanceCustomizeTable::getType, tableVos.getType()).eq(AttendanceCustomizeTable::getField, "customLeaveJson").last("limit 1").one();
        // 变更自定义假Json数据
        customLeaveJsonField.setCustomLeaveJson(JsonUtil.getObjectToString(typeJsonDataList));
        updateDataList.add(customLeaveJsonField);
        updateBatchById(updateDataList);
    }
}
