package cn.iocoder.yudao.module.configure.service.unitemplate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CodeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.configure.controller.admin.unitemplate.vo.*;
import cn.iocoder.yudao.module.configure.dal.dataobject.unitemplate.UniTemplateDO;
import cn.iocoder.yudao.module.configure.dal.dataobject.unitemplateitem.UniTemplateItemDO;
import cn.iocoder.yudao.module.configure.dal.mysql.unitemplate.UniTemplateMapper;
import cn.iocoder.yudao.module.configure.dal.mysql.unitemplateitem.UniTemplateItemMapper;
import cn.iocoder.yudao.module.configure.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.configure.enums.UniTemplateTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 小程序模板 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class UniTemplateServiceImpl implements UniTemplateService {

    @Resource
    private UniTemplateMapper uniTemplateMapper;

    @Resource
    private UniTemplateItemMapper uniTemplateItemMapper;

    @Override
    @Transactional
    public <T extends UniTemplateCreateReqVO> Long createUniTemplate(T createReqVO) {
        UniTemplateDO uniTemplate = new UniTemplateDO();
        List<UniTemplateItemDO> itemList = new ArrayList<>();

        BeanUtil.copyProperties(createReqVO, uniTemplate);
        // 校验重名
        this.validateSameName(null, uniTemplate.getTemplateName());
        uniTemplate.setTemplateId(CodeEnum.UNI_TEMPLATE_CODE.getCode());
        this.verifyIconAndSetIcon(uniTemplate);

        if (createReqVO instanceof UniTemplateCreateCustomizeReqVO) {
            // 该模板为自定义模板
            uniTemplate.setTemplateType(UniTemplateTypeEnum.CUSTOMIZE.getType());
            // 转换为自定义类型的模板
            UniTemplateCreateCustomizeReqVO customize = ((UniTemplateCreateCustomizeReqVO) createReqVO);
            if (customize.getTemplateItemList() != null) {
                customize.getTemplateItemList().forEach(item -> {
                    UniTemplateItemDO templateItem = new UniTemplateItemDO();
                    BeanUtil.copyProperties(item, templateItem);
                    templateItem.setTemplateId(uniTemplate.getTemplateId());
                    itemList.add(templateItem);
                });
            }
        } else {
            uniTemplate.setTemplateType(UniTemplateTypeEnum.STANDARD.getType());
            this.setDefaultForStandard(uniTemplate);
        }

        uniTemplateMapper.insert(uniTemplate);
        if (uniTemplate.getDefaultTemplate()) {
            // 更新旧的默认模板为非默认
            uniTemplateMapper.update(new UniTemplateDO().setDefaultTemplate(Boolean.FALSE),
                    new LambdaQueryWrapper<UniTemplateDO>().ne(UniTemplateDO::getId, uniTemplate.getId()));
        }

        if (itemList.isEmpty()) {
            uniTemplateItemMapper.insertBatch(itemList);
        }

        // 返回
        return uniTemplate.getId();
    }

    @Override
    @Transactional
    public <T extends UniTemplateUpdateReqVO> void updateUniTemplate(T updateReqVO) {
        // 校验存在
        UniTemplateDO templateDO = this.validateUniTemplateExists(updateReqVO.getId());
        if (templateDO.getDefaultTemplate() && !updateReqVO.getDefaultTemplate()) {
            throw exception(ErrorCodeConstants.MUST_BE_HAS_A_DEFAULT_TEMPLATE);
        }
        // 获取原本存在的环节信息
        List<UniTemplateItemDO> itemDBList = uniTemplateItemMapper.selectList(new LambdaQueryWrapper<UniTemplateItemDO>()
                .eq(UniTemplateItemDO::getTemplateId, templateDO.getTemplateId()));
        // 校验重名
        this.validateSameName(updateReqVO.getId(), updateReqVO.getTemplateName());
        UniTemplateDO update = new UniTemplateDO();
        List<UniTemplateItemDO> createItemList = new ArrayList<>();
        List<UniTemplateItemDO> updateItemList = new ArrayList<>();
        List<Long> deleteItemIds = new ArrayList<>();

        BeanUtil.copyProperties(updateReqVO, update);

        this.verifyIconAndSetIcon(update);

        if (updateReqVO instanceof UniTemplateUpdateCustomizeReqVO) {
            // 该模板为自定义模板
            update.setTemplateType(UniTemplateTypeEnum.CUSTOMIZE.getType());
            // 转换为自定义类型的模板
            UniTemplateUpdateCustomizeReqVO customize = ((UniTemplateUpdateCustomizeReqVO) updateReqVO);

            List<Long> DBIds = itemDBList.stream().map(UniTemplateItemDO::getId).collect(Collectors.toList());

            if (customize.getTemplateItemList() != null) {
                List<Long> reqIds = new ArrayList<>();
                customize.getTemplateItemList().forEach(item -> {
                    UniTemplateItemDO templateItem = new UniTemplateItemDO();
                    BeanUtil.copyProperties(item, templateItem);
                    if (templateItem.getId() == null) {
                        templateItem.setTemplateId(templateDO.getTemplateId());
                        createItemList.add(templateItem);
                    } else {
                        if (!DBIds.contains(item.getId())) {
                            throw exception(ErrorCodeConstants.UNI_TEMPLATE_ITEM_NOT_EXISTS);
                        }
                        updateItemList.add(templateItem);
                        reqIds.add(item.getId());
                    }
                });

                deleteItemIds.addAll(CollUtil.subtract(DBIds, reqIds));
            }
        } else {
            update.setTemplateType(UniTemplateTypeEnum.STANDARD.getType());
            this.setDefaultForStandard(update);

            if (!itemDBList.isEmpty()) {
                deleteItemIds.addAll(itemDBList.stream().map(UniTemplateItemDO::getId).collect(Collectors.toList()));
            }
        }

        uniTemplateMapper.updateById(update);
        if (update.getDefaultTemplate()) {
            // 更新旧的默认模板为非默认
            uniTemplateMapper.update(new UniTemplateDO().setDefaultTemplate(Boolean.FALSE),
                    new LambdaQueryWrapper<UniTemplateDO>().ne(UniTemplateDO::getId, update.getId()));
        }

        if (!createItemList.isEmpty()) {
            uniTemplateItemMapper.insertBatch(createItemList);
        }

        if (!updateItemList.isEmpty()) {
            uniTemplateItemMapper.updateBatch(updateItemList, updateItemList.size());
        }

        if (!deleteItemIds.isEmpty()) {
            uniTemplateMapper.deleteBatchIds(deleteItemIds);
        }
    }

    private void verifyIconAndSetIcon(UniTemplateDO templateDO) {
        if (templateDO.getShowScanRecord() && StringUtils.isBlank(templateDO.getScanRecordIconUrl())) {
            throw exception(ErrorCodeConstants.UNI_TEMPLATE_SCAN_RECORD_ICON_NOT_BE_NULL);
        } else if (!templateDO.getShowScanRecord()) {
            templateDO.setScanRecordIconUrl("");
        }

        if (templateDO.getShowChangeLanguage() && StringUtils.isBlank(templateDO.getChangeLanguageIconUrl())
                && templateDO.getTemplateType().equals(UniTemplateTypeEnum.CUSTOMIZE.getType())) {
            // 如果显示切换语言并且未上传语言图标并且类型为自定义模板时，报错
            throw exception(ErrorCodeConstants.UNI_TEMPLATE_LANGUAGE_ICON_NOT_BE_NULL);
        } else if (!templateDO.getShowChangeLanguage() || templateDO.getTemplateType().equals(UniTemplateTypeEnum.STANDARD.getType())) {
            templateDO.setChangeLanguageIconUrl("");
        }

        if (templateDO.getTemplateType().equals(UniTemplateTypeEnum.CUSTOMIZE.getType())) {
            if (templateDO.getShowGoodsDetail() && StringUtils.isBlank(templateDO.getGoodsDetailIconUrl())) {
                throw exception(ErrorCodeConstants.UNI_TEMPLATE_GOODS_DETAIL_ICON_NOT_BE_NULL);
            } else if (!templateDO.getShowGoodsDetail()) {
                templateDO.setGoodsDetailIconUrl("");
            }

            if (templateDO.getShowAi() && StringUtils.isBlank(templateDO.getAiIconUrl())) {
                throw exception(ErrorCodeConstants.UNI_TEMPLATE_AI_ICON_NOT_BE_NULL);
            } else if (!templateDO.getShowAi()) {
                templateDO.setAiIconUrl("");
            }

            if (templateDO.getShowShop() && StringUtils.isBlank(templateDO.getShopIconUrl())) {
                throw exception(ErrorCodeConstants.UNI_TEMPLATE_SHOP_ICON_NOT_BE_NULL);
            } else if (!templateDO.getShowShop()) {
                templateDO.setShopIconUrl("");
            }
        }
    }

    private void setDefaultForStandard(UniTemplateDO templateDO) {
        templateDO.setShowGoodsDetail(Boolean.TRUE);
        templateDO.setGoodsDetailIconUrl("");
        templateDO.setShowAi(Boolean.TRUE);
        templateDO.setAiIconUrl("");
        templateDO.setShowShop(Boolean.TRUE);
        templateDO.setShopIconUrl("");
    }

    @Override
    public void deleteUniTemplate(Long id) {
        // 校验存在
        UniTemplateDO templateDO = this.validateUniTemplateExists(id);
        if (templateDO.getDefaultTemplate()) {
            throw exception(ErrorCodeConstants.CAN_NOT_DELETE_DEFAULT_TEMPLATE);
        }
        // 删除
        uniTemplateMapper.deleteById(id);
    }

    private UniTemplateDO validateUniTemplateExists(Long id) {
        UniTemplateDO templateDO = uniTemplateMapper.selectById(id);
        if (templateDO == null) {
            throw exception(ErrorCodeConstants.UNI_TEMPLATE_NOT_EXISTS);
        }
        return templateDO;
    }

    private void validateSameName(Long id, String name) {
        UniTemplateDO templateDO = uniTemplateMapper.selectOne(new LambdaQueryWrapperX<UniTemplateDO>()
                .eq(UniTemplateDO::getTemplateName, name).neIfPresent(UniTemplateDO::getId, id));
        if (templateDO != null) {
            throw exception(ErrorCodeConstants.UNI_TEMPLATE_NAME_IS_SAME_EXISTS);
        }
    }

    @Override
    public UniTemplateRespVO getUniTemplate(Long id) {
        return uniTemplateMapper.getUniTemplateDetail(id);
    }

    @Override
    public PageResult<UniTemplateRespVO> getUniTemplatePage(UniTemplatePageReqVO pageReqVO) {
        Page<UniTemplateRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<UniTemplateRespVO> result = uniTemplateMapper.selectUniTemplatePage(page, pageReqVO);
        return new PageResult<>(result, page.getTotal());
    }

    @Override
    public UniTemplateDO getDefaultUniTemplate() {
        return uniTemplateMapper.selectOne(new LambdaQueryWrapperX<UniTemplateDO>().eq(UniTemplateDO::getDefaultTemplate, Boolean.TRUE));
    }

    @Override
    public List<UniTemplateOptionVO> getOptions() {
        List<UniTemplateDO> list = uniTemplateMapper.selectList(new LambdaQueryWrapperX<UniTemplateDO>().select(UniTemplateDO::getId, UniTemplateDO::getTemplateName));
        return list.stream().map(item -> new UniTemplateOptionVO(item.getId(), item.getTemplateName())).collect(Collectors.toList());
    }

}
