package com.jwipc.sys.logic.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.constant.DictCode;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import com.jwipc.sys.constant.DealtTargetCategroy;
import com.jwipc.sys.convert.DealtInfoConvert;
import com.jwipc.sys.convert.DealtWithTargetTypeConvert;
import com.jwipc.sys.dto.DealtWithTargetInfoDTO;
import com.jwipc.sys.dto.DealtWithTargetInfoTreeDTO;
import com.jwipc.sys.dto.UserDWTDTO;
import com.jwipc.sys.dto.UserDwtItemDTO;
import com.jwipc.sys.entity.DealtWithTargetInfo;
import com.jwipc.sys.entity.DealtWithTargetType;
import com.jwipc.sys.logic.DealtInfoLogic;
import com.jwipc.sys.model.po.DealtWithTargetInfoPO;
import com.jwipc.sys.model.po.DictByTypePO;
import com.jwipc.sys.model.po.UserDwtItemPO;
import com.jwipc.sys.model.query.DealtInfoQuery;
import com.jwipc.sys.service.IDealtWithTargetInfoService;
import com.jwipc.sys.service.IDealtWithTargetTypeService;
import com.jwipc.sys.service.IDictService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author shenyang.ou
 * @date 2024/1/30 13:05
 * @desc 指标
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DealtInfoLogicImpl implements DealtInfoLogic {
    private final IDealtWithTargetInfoService dealtWithTargetInfoService;
    private final DealtInfoConvert dealtInfoConvert;
    private final IDictService dictService;
    private final IDealtWithTargetTypeService dealtWithTargetTypeService;
    private final DealtWithTargetTypeConvert dealtWithTargetTypeConvert;

    @Override
    public PageView findByPage(DealtInfoQuery query) {
        final Page<DealtWithTargetInfo> dbPage = PageUtil.toPage(query);
        List<DealtWithTargetInfoPO> dealtWithTargetInfoPOS = dealtWithTargetInfoService.findPageByQuery(dbPage, query);
        return PageUtil.getPV(dealtInfoConvert.po2DTOList(dealtWithTargetInfoPOS), dbPage.getTotal());
    }

    @Override
    public DealtWithTargetInfoDTO getById(Long id) {
        DealtWithTargetInfoPO info = dealtWithTargetInfoService.getDataById(id);
        return dealtInfoConvert.po2DTO(info);
    }

    @Override
    public void saveOrUpdate(DealtWithTargetInfoDTO param) {
        //保存
        if (param.getId() == null) {
            if (ObjectUtil.isNotNull(dealtWithTargetInfoService.getOne(new LambdaQueryWrapper<DealtWithTargetInfo>().eq(
                    DealtWithTargetInfo::getCode, param.getCode()).last(" limit 1")))) {
                throw new DaoException("指标编码已经存在, 请检查");
            }
            param.setCreateTime(LocalDateTime.now());
            param.setCreateUser(Objects.requireNonNull(LoginUtil.getCurrentUser()).getUserId());
        } else {
            if (ObjectUtil.isNotNull(dealtWithTargetInfoService.getOne(new LambdaQueryWrapper<DealtWithTargetInfo>().eq(
                            DealtWithTargetInfo::getCode, param.getCode()).ne(DealtWithTargetInfo::getId, param.getId())
                    .last(" limit 1")))) {
                throw new DaoException("指标编码已经存在, 请检查");
            }
            param.setModifyTime(LocalDateTime.now());
            param.setModifyUser(Objects.requireNonNull(LoginUtil.getCurrentUser()).getUserId());
        }
        dealtWithTargetInfoService.saveOrUpdate(dealtInfoConvert.dto2Entity(param));
    }

    @Override
    public void remove(Long id) {
        dealtWithTargetInfoService.removeById(id);
    }

    @Override
    public List<DealtWithTargetInfoTreeDTO> getTreeGrid() {
        final List<DealtWithTargetInfo> list = dealtWithTargetInfoService.list();
        final List<DictByTypePO> dictByType = dictService.findDictByType(DictCode.DEAL_WITH_TARGET_CLASS.getCode());
        final Map<String, String> dictMap = dictByType.stream()
                .collect(Collectors.toMap(DictByTypePO::getCode, DictByTypePO::getName));
        // 所有待办指标按指标类型分组 Map<指标类型值, 指标类型描述>
        Map<String, String> map = Maps.newHashMap();
        for (DealtWithTargetInfo dto : list) {
            if (StringUtils.isEmpty(map.get(dto.getCategory()))) {
                map.put(dto.getCategory(), dictMap.get(dto.getCategory()));
            }
        }
        final List<DealtWithTargetType> dealtWithTargetTypes = dealtWithTargetTypeService.list();
        final Map<Long, DealtWithTargetType> dealtWithTargetTypeMap = dealtWithTargetTypes.stream()
                .collect(Collectors.toMap(DealtWithTargetType::getId, a -> a));
        // 所有待办指标按指标分类分组 Map<指标分类ID, 指标分类描述#指标分类排序>
        Map<Long, String> classifyMap = Maps.newHashMap();
        for (DealtWithTargetInfo dto : list) {
            if (StringUtils.isEmpty(classifyMap.get(dto.getTargetTypeId()))) {
                final DealtWithTargetType dealtWithTargetType = dealtWithTargetTypeMap.get(dto.getTargetTypeId());
                final String value;
                if (Objects.nonNull(dealtWithTargetType)) {
                    value = dealtWithTargetType.getName() + "#" + dealtWithTargetType.getSort();
                } else {
                    value = "null#null";
                }

                classifyMap.put(dto.getTargetTypeId(), value);
            }
        }

        List<DealtWithTargetInfoTreeDTO> returnList = Lists.newArrayList();
        List<String> categoryList = list.stream().map(DealtWithTargetInfo::getCategory).distinct().collect(
                Collectors.toList());
        for (String category : categoryList) {
            String id = UUID.randomUUID().toString();
            DealtWithTargetInfoTreeDTO dealtWithTargetInfoTreeDto = new DealtWithTargetInfoTreeDTO();
            dealtWithTargetInfoTreeDto.setId(id);
            dealtWithTargetInfoTreeDto.setCode(category);
            dealtWithTargetInfoTreeDto.setText(map.get(category));
            returnList.add(dealtWithTargetInfoTreeDto);

            List<DealtWithTargetInfoTreeDTO> categoryChildrenList = Lists.newArrayList();
            dealtWithTargetInfoTreeDto.setChildren(categoryChildrenList);

            List<Long> classifyList = list.stream().filter(item -> item.getCategory().equals(category))
                    .map(DealtWithTargetInfo::getTargetTypeId).distinct().collect(Collectors.toList());
            for (Long classify : classifyList) {
                String classifyId = UUID.randomUUID().toString();
                DealtWithTargetInfoTreeDTO classifyTreeDto = new DealtWithTargetInfoTreeDTO();
                classifyTreeDto.setId(classifyId);
                classifyTreeDto.setParentId(id);
                classifyTreeDto.setCode(classify + StringUtils.EMPTY);

                final String[] classifyArray = classifyMap.get(classify).split("#");
                classifyTreeDto.setText(classifyArray[0]);
                if (classifyArray[1] != null && !classifyArray[1].equals("null")) {
                    classifyTreeDto.setSort(Integer.valueOf(classifyArray[1]));
                }

                List<DealtWithTargetInfo> detailList = list.stream()
                        .filter(item -> item.getCategory().equals(category) && item.getTargetTypeId().equals(classify))
                        .collect(Collectors.toList());
                List<DealtWithTargetInfoTreeDTO> classifyChildrenTreeDtoList = Lists.newArrayList();
                for (DealtWithTargetInfo dealtWithTargetInfoDto : detailList) {
                    DealtWithTargetInfoTreeDTO treeDto = new DealtWithTargetInfoTreeDTO();
                    treeDto.setId(dealtWithTargetInfoDto.getId().toString());
                    treeDto.setParentId(classifyId);
                    treeDto.setCode(dealtWithTargetInfoDto.getCode());
                    if (StringUtils.isNotBlank(dealtWithTargetInfoDto.getDescription())) {
                        treeDto.setText(
                                dealtWithTargetInfoDto.getName() + "(" + dealtWithTargetInfoDto.getDescription() + ")");
                    } else {
                        treeDto.setText(dealtWithTargetInfoDto.getName());
                    }
                    treeDto.setIsLast(1);
                    treeDto.setSort(dealtWithTargetInfoDto.getSort());
                    classifyChildrenTreeDtoList.add(treeDto);
                }
                classifyTreeDto.setChildren(classifyChildrenTreeDtoList);
                categoryChildrenList.add(classifyTreeDto);
            }
        }
        return returnList;
    }

    @Override
    public List<UserDWTDTO> getUserDealtWith() {
        return getUserDWTDTOS(DealtTargetCategroy.DEALTWITH);
    }
    @Override
    public List<UserDWTDTO> getUserEarlyWarning() {
        return getUserDWTDTOS(DealtTargetCategroy.REMIND);
    }

    private @NotNull List<UserDWTDTO> getUserDWTDTOS(DealtTargetCategroy dealtTargetCategroy) {
        final Long userId = LoginUtil.getUserId();
        final String userName = LoginUtil.getName();
        final String account = LoginUtil.getAccount();
        List<UserDwtItemPO> dwtList = dealtWithTargetInfoService.selectUserDwtData(userId,
                dealtTargetCategroy.getType());
        for (UserDwtItemPO dto : dwtList) {
            if (ObjectUtil.isNull(dto.getResId())) {
                String temp = dto.getTargetTypeId().toString() + dto.getDwtId().toString();
                dto.setResId(Long.parseLong(temp));
            }
        }
        List<Long> ttIdList = Lists.newArrayList();
        for (UserDwtItemPO dwt : dwtList) {
            String sql = dwt.getDwtSql();
            if (sql.contains("#{q.userId}")) {
                sql = StringUtils.replace(dwt.getDwtSql(), "#{q.userId}", userId.toString());
            }
            if (sql.contains("#{q.userCode}")) {
                sql = StringUtils.replace(sql, "#{q.userCode}", userName);
            }
            if (sql.contains("#{q.supplierCode}")) {
                if (!LoginUtil.isSupplier()) {
                    sql = StringUtils.replace(sql, "#{q.supplierCode}", "'0'");
                } else {
                    sql = StringUtils.replace(sql, "#{q.supplierCode}", "'" + account + "'");
                }
            }
            if (sql.contains("#{q.supplierId}")) {
                if (!LoginUtil.isSupplier()) {
                    sql = StringUtils.replace(sql, "#{q.supplierId}", "0");
                } else {
                    Long supplierId = LoginUtil.getSupplierId();
                    sql = StringUtils.replace(sql, "#{q.supplierId}", String.valueOf(supplierId));
                }
            }
            try {
                dwt.setDwtTotalNum(this.dealtWithTargetInfoService.getSqlCount(sql));
            } catch (Exception e) {
                log.info("SQL语句执行异常，{}", e.getMessage(), e);
            }

            if (!ttIdList.contains(dwt.getTargetTypeId())) {
                ttIdList.add(dwt.getTargetTypeId());
            }
        }

        final List<DealtWithTargetType> dealtWithTargetTypes = dealtWithTargetTypeService.findByIds(ttIdList);
        List<UserDWTDTO> result = dealtWithTargetTypeConvert.entities2DTOs(dealtWithTargetTypes);
        for (UserDWTDTO dto : result) {
            Long ttId = dto.getTargetTypeId();
            List<UserDwtItemDTO> itemList = Lists.newArrayList();
            List<UserDwtItemDTO> userDwtItemDTOS = dealtWithTargetTypeConvert.pos2DTOs(dwtList);
            for (UserDwtItemDTO item : userDwtItemDTOS) {
                if (item.getTargetTypeId().equals(ttId)) {
                    itemList.add(item);
                }
            }

            dto.setDwtList(itemList);
        }
        return result;
    }
}
