package cn.ey.biz.module.system.service.app;

import cn.ey.biz.common.exception.ErrorCode;
import cn.ey.biz.common.pojo.PageResult;
import cn.ey.biz.framework.mybatis.core.util.MyBatisUtils;
import cn.ey.biz.module.system.api.app.dto.AppDTO;
import cn.ey.biz.module.system.controller.admin.app.vo.*;
import cn.ey.biz.module.system.controller.admin.i18n.vo.I18nRespVO;
import cn.ey.biz.module.system.convert.app.AppConvert;
import cn.ey.biz.module.system.convert.i18n.I18nConvert;
import cn.ey.biz.module.system.dal.dataobject.app.AppDO;
import cn.ey.biz.module.system.dal.dataobject.i18n.I18nDO;
import cn.ey.biz.module.system.dal.mapper.app.AppMapper;
import cn.ey.biz.module.system.dal.mapper.i18n.I18nBatchInsertMapper;
import cn.ey.biz.module.system.dal.mapper.i18n.I18nMapper;
import cn.ey.biz.module.system.enums.i18n.I18nEnum;
import cn.ey.biz.module.system.mq.producer.i8n.I18nProducer;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static cn.ey.biz.common.exception.util.ServiceExceptionUtil.exception;
import static cn.ey.biz.module.system.enums.ErrorCodeConstants.*;

/**
 * 系统应用 Service 实现类
 */
@Service
@Validated
public class AppServiceImpl implements AppService {

    @Resource
    private AppMapper appMapper;

    @Resource
    private I18nBatchInsertMapper i18nBatchInsertMapper;

    @Resource
    private I18nProducer i18nProducer;

    @Resource
    private I18nMapper i18nMapper;

    @Override
    public Long createApp(AppCreateReqVO createReqVO) {
        // 校验Code
        checkCodeRepetition(null, createReqVO.getCode());
        // 校验Name
        checkNameRepetition(null, createReqVO.getName());
        // 插入
        AppDO app = AppConvert.INSTANCE.convert(createReqVO);
        appMapper.insert(app);
        // 添加到多语言
        List<I18nDO> i18nDOS = new ArrayList<>();
        List<String> list = Lists.newArrayList();
        if (CollectionUtil.isNotEmpty(createReqVO.getLangs())) {
            for (I18nRespVO lang : createReqVO.getLangs()) {
                if (list.contains(lang.getLang() + lang.getKey())) {
                    throw exception(I18N_LEAST_LANG_NOT_REPETITION, lang.getLang());
                } else {
                    list.add(lang.getLang() + lang.getKey());
                }
                I18nDO i18nDO = new I18nDO()
                        .setType(I18nEnum.APP.getType())
                        .setKey(String.valueOf(app.getId()))
                        .setLang(lang.getLang())
                        .setLabel(lang.getLabel());
                i18nDOS.add(i18nDO);
            }
            i18nBatchInsertMapper.saveBatch(i18nDOS);
            // 刷新多语言
            i18nProducer.sendI18nRefreshMessage();
        }
        // 返回
        return app.getId();
    }

    @Override
    public void importApp(@Valid List<AppDTO> appDTOs) {
        List<AppCreateReqVO> createReqVO = AppConvert.INSTANCE.convertDtoList(appDTOs);

        createReqVO.forEach(vo -> {
            AppDO doo = appMapper.selectOne(new LambdaQueryWrapper<AppDO>().eq(AppDO::getCode, vo.getCode()));
            if (doo == null) {
                appMapper.insert(AppConvert.INSTANCE.convert(vo));
            }
        });
    }

    @Override
    public void updateApp(AppUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateAppExists(updateReqVO.getId());
        // 校验Code
        checkCodeRepetition(updateReqVO.getId(), updateReqVO.getCode());
        // 校验Name
        checkNameRepetition(updateReqVO.getId(), updateReqVO.getName());
        // 更新
        AppDO updateObj = AppConvert.INSTANCE.convert(updateReqVO);
        appMapper.updateById(updateObj);
        // 更新到多语言
        if (CollectionUtil.isNotEmpty(updateReqVO.getLangs())) {
            LambdaUpdateWrapper<I18nDO> queryWrapper = Wrappers.<I18nDO>lambdaUpdate()
                    .eq(I18nDO::getKey, String.valueOf(updateReqVO.getId()))
                    .eq(I18nDO::getType, I18nEnum.APP.getType());
            i18nMapper.delete(queryWrapper);
            List<I18nDO> i18nDOS = new ArrayList<>();
            List<String> list = Lists.newArrayList();
            for (I18nRespVO lang : updateReqVO.getLangs()) {
                if (list.contains(lang.getLang() + lang.getKey())) {
                    throw exception(I18N_LEAST_LANG_NOT_REPETITION, lang.getLang());
                } else {
                    list.add(lang.getLang() + lang.getKey());
                }
                I18nDO i18nDO = new I18nDO()
                        .setType(I18nEnum.APP.getType())
                        .setKey(String.valueOf(updateReqVO.getId()))
                        .setLang(lang.getLang())
                        .setLabel(lang.getLabel());
                i18nDOS.add(i18nDO);
            }
            i18nBatchInsertMapper.saveBatch(i18nDOS);
            // 刷新多语言
            i18nProducer.sendI18nRefreshMessage();
        }
    }

    @Override
    public void deleteApp(Long id) {
        // 校验存在
        this.validateAppExists(id);
        // 删除与多语言关联的数据
        LambdaQueryWrapper<I18nDO> DeleteMenuWrapper = Wrappers.<I18nDO>lambdaQuery()
                .eq(I18nDO::getKey, String.valueOf(id))
                .eq(I18nDO::getType, I18nEnum.APP.getType());
        i18nMapper.delete(DeleteMenuWrapper);
        // 删除
        appMapper.deleteById(id);
    }

    private void validateAppExists(Long id) {
        if (appMapper.selectById(id) == null) {
            throw exception(APP_NOT_EXISTS);
        }
    }

    @Override
    public AppRespVO getApp(Long id) {
        AppDO app = appMapper.selectById(id);
        // 校验
        if (app == null) {
            throw exception(new ErrorCode(-1, "应用为空"));
        }
        AppRespVO appRespVO = AppConvert.INSTANCE.convert(app);
        LambdaQueryWrapper<I18nDO> queryWrapper = Wrappers.<I18nDO>lambdaQuery()
                .eq(I18nDO::getKey, id)
                .eq(I18nDO::getType, I18nEnum.APP.getType());
        List<I18nDO> i18nDOS = i18nMapper.selectList(queryWrapper);
        List<I18nRespVO> i18nRespVOS = I18nConvert.INSTANCE.convertList(i18nDOS);
        // 赋值
        appRespVO.setLangs(i18nRespVOS);
        return appRespVO;
    }

    @Override
    public List<AppDO> getAppList(Collection<Long> ids) {
        return appMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<AppRespVO> getAppPage(AppPageReqVO appPageReqVO, String acceptLanguage) {
        IPage page = MyBatisUtils.buildPage(appPageReqVO);
        IPage<AppRespVO> result = appMapper.selectPageApp(page, appPageReqVO, acceptLanguage);
        return new PageResult<AppRespVO>(result.getRecords(), result.getTotal());
    }

    @Override
    public List<AppDO> getAppList(AppExportReqVO exportReqVO) {
        return appMapper.selectList(exportReqVO);
    }

    @Override
    public List<AppDO> getAppList() {
        LambdaQueryWrapper<AppDO> wrappers = Wrappers.lambdaQuery(AppDO.class)
                .eq(AppDO::getAppType, "4")
                .eq(AppDO::getStatus, 0);
        return appMapper.selectList(wrappers);
    }

    @Override
    public List<AppDO> getAllApp() {
        return appMapper.selectList();
    }

    // 校验code
    private void checkCodeRepetition(Long id, String code) {
        // 添加校验
        LambdaQueryWrapper<AppDO> queryWrapper = Wrappers.<AppDO>lambdaQuery()
                .eq(AppDO::getCode, code);
        AppDO appDO = appMapper.selectOne(queryWrapper);
        if (id == null) {
            if (appDO != null) {
                throw exception(APP_CODE_REPETITION);
            }
        } else { // 修改校验
            if (appDO != null && appDO.getId() != id) {
                throw exception(APP_CODE_REPETITION);
            }
        }
    }

    // 校验Name
    private void checkNameRepetition(Long id, String name) {
        // 添加校验
        LambdaQueryWrapper<AppDO> queryWrapper = Wrappers.<AppDO>lambdaQuery()
                .eq(AppDO::getName, name);
        AppDO appDO = appMapper.selectOne(queryWrapper);
        if (id == null) {
            if (appDO != null) {
                throw exception(APP_NAME_REPETITION);
            }
        } else { // 修改校验
            if (appDO != null && appDO.getId() != id) {
                throw exception(APP_NAME_REPETITION);
            }
        }
    }

}
