package com.jwipc.sys.logic.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.jwipc.constant.DelFlag;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.sys.convert.PurchaseGroupConvert;
import com.jwipc.sys.convert.PurchaseGroupFactoryConvert;
import com.jwipc.sys.convert.UserPurchaseGroupConvert;
import com.jwipc.sys.dto.*;
import com.jwipc.sys.entity.PurchaseGroup;
import com.jwipc.sys.entity.PurchaseGroupFactory;
import com.jwipc.sys.entity.UserPurchaseGroup;
import com.jwipc.sys.logic.FileLogic;
import com.jwipc.sys.logic.PurchaseGroupLogic;
import com.jwipc.sys.model.param.PurchaseGroupParam;
import com.jwipc.sys.model.po.PurchaseGroupPO;
import com.jwipc.sys.model.po.UserPurchaseGroupPO;
import com.jwipc.sys.model.query.PurchaseGroupFactoryQuery;
import com.jwipc.sys.model.query.PurchaseGroupQuery;
import com.jwipc.sys.model.query.UserPurchaseGroupUpdateQuery;
import com.jwipc.sys.service.IPurchaseGroupFactoryService;
import com.jwipc.sys.service.IPurchaseGroupService;
import com.jwipc.sys.service.IUserPurchaseGroupService;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 采购组主数据 服务实现类
 * </p>
 *
 * @author AL
 * @since 2024-01-29
 */
@Service
@RequiredArgsConstructor
public class PurchaseGroupLogicImpl implements PurchaseGroupLogic {
    private final IPurchaseGroupService purchaseGroupService;
    private final PurchaseGroupConvert purchaseGroupConvert;
    private final IUserPurchaseGroupService userPurchaseGroupService;
    private final IPurchaseGroupFactoryService purchaseGroupFactoryService;
    private final UserPurchaseGroupConvert uerPurchaseGroupConvert;
    private final PurchaseGroupFactoryConvert purchaseGroupFactoryConvert;
    private final FileLogic fileLogic;

    @Override
    public PageView findByPage(PurchaseGroupQuery query) {
        final Page<PurchaseGroup> dbPage = PageUtil.toPage(query);

        List<PurchaseGroupPO> purchaseGroupPOS = purchaseGroupService.findPageByQuery(dbPage, query);

        return PageUtil.getPV(purchaseGroupConvert.po2PageListDTO1(purchaseGroupPOS), dbPage.getTotal());
    }

    @Override
    public List<com.jwipc.sys.dto.PurchaseGroupDTO> listAll(PurchaseGroupQuery query) {
        List<PurchaseGroupPO> purchaseGroupPOS = purchaseGroupService.findPageByQuery(null, query);
        return purchaseGroupConvert.po2PageListDTO1(purchaseGroupPOS);
    }

    @Override
    public com.jwipc.sys.dto.PurchaseGroupDTO getById(Long id) {
        if (id != null) {
            PurchaseGroupPO purchaseGroupPO = purchaseGroupService.getDataById(id);
            return purchaseGroupConvert.po2DTO(purchaseGroupPO);
        } else {
            return new PurchaseGroupDTO();
        }
    }
    @Override
    public com.jwipc.sys.dto.PurchaseGroupDTO getByCode(String purchaseGroupCode) {
        if (purchaseGroupCode != null) {
            PurchaseGroupPO purchaseGroupPO = purchaseGroupService.getDataByCode(purchaseGroupCode);
            return purchaseGroupConvert.po2DTO(purchaseGroupPO);
        } else {
            return new PurchaseGroupDTO();
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdate(PurchaseGroupParam param) {
        //保存
//        Objects.nonNull();
//        Objects.isNull()
        if (Objects.isNull(param.getId())) {
            final LambdaQueryWrapper<PurchaseGroup> resourcesLambdaQueryWrapper =
                    new LambdaQueryWrapper<PurchaseGroup>().eq(
                            PurchaseGroup::getPurchaseGroupCode, param.getPurchaseGroupCode()).last(" limit 1");
            if (ObjectUtil.isNotNull(purchaseGroupService.getOne(resourcesLambdaQueryWrapper))) {
                throw new DaoException("采购组编码重复");
            }

            param.setCreateTime(LocalDateTime.now());
            param.setDataPrimary(param.getOrgCode() + param.getPurchaseGroupCode());


        } else {
            final LambdaQueryWrapper<PurchaseGroup> resourcesLambdaQueryWrapper =
                    new LambdaQueryWrapper<PurchaseGroup>().eq(
                                    PurchaseGroup::getPurchaseGroupCode, param.getPurchaseGroupCode())
                            .ne(PurchaseGroup::getId, param.getId()).last(" limit 1");
            if (ObjectUtil.isNotNull(purchaseGroupService.getOne(resourcesLambdaQueryWrapper))) {
                throw new DaoException("采购组编码重复");
            }
            param.setLastUpdateTime(LocalDateTime.now());


        }
        purchaseGroupService.saveOrUpdate(purchaseGroupConvert.param2Entity(param));
    }

    @Override
    public void remove(String purchaseGroupCode) {
        //删除
        purchaseGroupService.remove(
                new LambdaQueryWrapper<PurchaseGroup>().eq(PurchaseGroup::getPurchaseGroupCode, purchaseGroupCode));
    }

    @Override
    public List<UserPurGroupTreeDTO> getForTree(Long userId) {
        final LambdaQueryWrapper<UserPurchaseGroup> userPurchaseGroupLambdaQueryWrapper =
                new LambdaQueryWrapper<UserPurchaseGroup>().eq(
                        UserPurchaseGroup::getUserId, userId);
        final List<UserPurchaseGroup> userPurchaseGroups = userPurchaseGroupService.list(
                userPurchaseGroupLambdaQueryWrapper);
        final List<Long> userHas = userPurchaseGroups.stream().map(UserPurchaseGroup::getPurchaseGroupId)
                .collect(Collectors.toList());
        final List<Long> userDefault = userPurchaseGroups.stream()
                .filter(a -> Objects.nonNull(a.getMark()) && a.getMark() == 1)
                .map(UserPurchaseGroup::getPurchaseGroupId)
                .collect(Collectors.toList());
        final LambdaQueryWrapper<PurchaseGroup> purchaseGroupLambdaQueryWrapper =
                new LambdaQueryWrapper<PurchaseGroup>().eq(
                                PurchaseGroup::getDeleteFlag, DelFlag.NORMAL.getStatus())
                        .orderBy(true, true, PurchaseGroup::getPurchaseGroupCode);
        final List<PurchaseGroup> purchaseGroupList = purchaseGroupService.list(purchaseGroupLambdaQueryWrapper);
        List<UserPurGroupTreeDTO> list = Lists.newArrayList();
        UserPurGroupTreeDTO userPurGroupTreeDTO = new UserPurGroupTreeDTO();
        userPurGroupTreeDTO.setId(-1L);
        userPurGroupTreeDTO.setText("采购组选择");
        userPurGroupTreeDTO.setState("closed");
        userPurGroupTreeDTO.setLevel("0");
        userPurGroupTreeDTO.setChecked(false);
        userPurGroupTreeDTO.setDefaultFlag(false);
        userPurGroupTreeDTO.setChildren(Lists.newArrayList());
        list.add(userPurGroupTreeDTO);
        for (PurchaseGroup purchaseGroup : purchaseGroupList) {
            UserPurGroupTreeDTO userPurGroupTreeDTO1 = new UserPurGroupTreeDTO();
            userPurGroupTreeDTO1.setId(purchaseGroup.getId());
            userPurGroupTreeDTO1.setText(StrUtil.format("({}){}", purchaseGroup.getPurchaseGroupCode(),
                    purchaseGroup.getPurchaseGroupName()));
            userPurGroupTreeDTO1.setState("closed");
            userPurGroupTreeDTO1.setLevel("1");
            userPurGroupTreeDTO1.setChecked(userHas.contains(purchaseGroup.getId()));
            userPurGroupTreeDTO1.setDefaultFlag(userDefault.contains(purchaseGroup.getId()));
            userPurGroupTreeDTO.getChildren().add(userPurGroupTreeDTO1);
        }
        return list;
    }

    @Override
    public PageView getFactoryList(PurchaseGroupFactoryQuery query) {
        final Page<PurchaseGroupFactory> page = PageUtil.toPage(query);
        final LambdaQueryWrapper<PurchaseGroupFactory> queryWrapper = getQueryWrapper(
                query);
        final List<PurchaseGroupFactory> list = purchaseGroupFactoryService.list(page, queryWrapper);
        List<PurchaseGroupFactoryListDTO> list1 = purchaseGroupFactoryConvert.entites2ListDTOs(list);
        return PageUtil.getPV(list1, page.getTotal());
    }

    @NotNull
    private static LambdaQueryWrapper<PurchaseGroupFactory> getQueryWrapper(
            PurchaseGroupFactoryQuery query)
    {
        final LambdaQueryWrapper<PurchaseGroupFactory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotEmpty(query.getMaterialGroupCode()), PurchaseGroupFactory::getMaterialGroupCode,
                query.getMaterialGroupCode());
        queryWrapper.like(StrUtil.isNotEmpty(query.getMaterialGroupName()), PurchaseGroupFactory::getPurchaseGroupName,
                query.getPurchaseGroupName());
        queryWrapper.like(StrUtil.isNotEmpty(query.getPurchaseGroupCode()), PurchaseGroupFactory::getPurchaseGroupCode,
                query.getPurchaseGroupCode());
        queryWrapper.like(StrUtil.isNotEmpty(query.getPurchaseGroupName()), PurchaseGroupFactory::getPurchaseGroupName,
                query.getPurchaseGroupName());
        queryWrapper.eq(StrUtil.isNotEmpty(query.getFactoryCode()), PurchaseGroupFactory::getFactoryCode,
                query.getFactoryCode());
        queryWrapper.eq(Objects.nonNull(query.getDeleteFlag()), PurchaseGroupFactory::getDeleteFlag,
                query.getDeleteFlag());
        return queryWrapper;
    }

    @Override
    public void factoryImportData(MultipartFile file) {
        List<PurchaseGroupFactoryImportDTO> cachedDataList = ListUtils.newArrayList();
        try {
            EasyExcel.read(file.getInputStream(), PurchaseGroupFactoryImportDTO.class,
                    new ReadListener<PurchaseGroupFactoryImportDTO>() {
                        @Override
                        public void invoke(PurchaseGroupFactoryImportDTO data, AnalysisContext context) {
                            final String code = data.getFactoryCode();
                            if (Strings.isNullOrEmpty(code)) {
                                throw new DaoException("工厂编码不能为空!");
                            }
                            if (Strings.isNullOrEmpty(data.getMaterialGroupCode())) {
                                throw new DaoException("物料组编码不能为空!");
                            }
                            if (Strings.isNullOrEmpty(data.getPurchaseGroupCode())) {
                                throw new DaoException("采购组编码不能为空!");
                            }
                            cachedDataList.add(data);
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                        }
                    }).sheet().doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        List<PurchaseGroupFactory> dicts = purchaseGroupFactoryConvert.importDTOs2Entites(cachedDataList);
        for (PurchaseGroupFactory dict : dicts) {
            dict.setCreateTime(LocalDateTime.now());
            dict.setDeleteFlag(DelFlag.NORMAL.getStatus());
        }
        purchaseGroupFactoryService.saveBatch(dicts);
    }

    @Override
    public List<PurchaseGroupFactoryExportDTO> getFactoryForExport(PurchaseGroupFactoryQuery query) {
        final LambdaQueryWrapper<PurchaseGroupFactory> queryWrapper = getQueryWrapper(
                query);
        final List<PurchaseGroupFactory> list = purchaseGroupFactoryService.list(queryWrapper);
        return purchaseGroupFactoryConvert.entites2ExportDTOs(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFactoryStatus(String ids, Integer status) {
        final List<String> split = StrUtil.split(ids, StrUtil.COMMA);
        final LambdaUpdateWrapper<PurchaseGroupFactory> updateWrapper =
                new LambdaUpdateWrapper<>();
        updateWrapper.set(PurchaseGroupFactory::getDeleteFlag, status)
                .in(PurchaseGroupFactory::getId, split);
        purchaseGroupFactoryService.update(updateWrapper);
    }

    @Override
    public List<UserPurchaseGroupUpdateDTO> createListAll(UserPurchaseGroupUpdateQuery query) {
        List<UserPurchaseGroupPO> userPurchaseGroupPOS = userPurchaseGroupService.findPageByQueryC(null, query);
        return uerPurchaseGroupConvert.po2PageListDTOC(userPurchaseGroupPOS);
    }
}
