package com.mosty.common.config.controller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.mosty.common.base.constant.enums.DeletedEnum;
import com.mosty.common.base.domain.ResponseResult;
import com.mosty.common.base.entity.log.BusinessType;
import com.mosty.common.base.entity.log.Log;
import com.mosty.common.base.exception.Asserts;
import com.mosty.common.base.util.ChineseCharacterUtil;
import com.mosty.common.base.util.IpUtil;
import com.mosty.common.config.Excel.DictUtils;
import com.mosty.common.config.entity.SysDict;
import com.mosty.common.config.entity.SysDictItem;
import com.mosty.common.config.entity.vo.*;
import com.mosty.common.config.service.SysDictItemService;
import com.mosty.common.config.service.SysDictService;
import com.mosty.common.token.JwtSysUser;
import com.mosty.common.token.UserInfo;
import com.mosty.common.token.UserInfoManager;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 字典代码值表 前端控制器
 * </p>
 *
 * @author kevin
 * @since 2022-02-09
 */
@SuppressWarnings("unused")
@RestController
@AllArgsConstructor
@RequestMapping("/sys-dict-item")
@Api(tags = "字典明细接口")
public class SysDictItemController {

    private final SysDictService sysDictService;
    private final SysDictItemService sysDictItemService;

    /**
     * 根据字典明细编号查询子字典明细信息
     *
     * @param dictItemCode 字典明细编码
     * @return 字典信息
     */
    @GetMapping("getChildItemByCode")
    @ApiOperation(value = "根据字典明细编号查询子字典明细信息", httpMethod = "GET", response = SysDictItemVO.class)
    public ResponseResult<List<SysDictItemVO>> getChildItemByCode(String dictItemCode) {
        SysDictItem sysDictItem = checkAndGetItem(dictItemCode);

        QueryWrapper<SysDictItem> queryChildWrapper = new QueryWrapper<>();
        queryChildWrapper.eq("zd_id", sysDictItem.getId());
        List<SysDictItem> list = sysDictItemService.list(queryChildWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return ResponseResult.success(Lists.newArrayList());
        }
        List<SysDictItemVO> sysDictItemVOS = BeanUtil.copyToList(list, SysDictItemVO.class);
        List<SysDictItemVO> collect = sysDictItemVOS.stream().sorted(Comparator.comparing(SysDictItemVO::getPx).reversed()).collect(Collectors.toList());
        return ResponseResult.success(collect);
    }

    /**
     * 根据字典明细编号，查询所有子字典明细信息
     *
     * @param dictItemCode 字典明细编码
     * @return 字典信息
     */
    @GetMapping("getAllChildItemByCode")
    @ApiOperation(value = "根据字典明细编号，查询所有子字典明细信息", httpMethod = "GET", response = SysDictItemVO.class)
    public ResponseResult<List<SysDictItemVO>> getAllChildItemByCode(String dictItemCode) {
        SysDictItem sysDictItem = checkAndGetItem(dictItemCode);
        SysDictItemVO sysDictItemVO = BeanUtil.copyProperties(sysDictItem, SysDictItemVO.class);

        QueryWrapper<SysDictItem> queryChildWrapper = new QueryWrapper<>();
        queryChildWrapper.eq("root_path", sysDictItem.getRootPath());
        List<SysDictItem> allDict = sysDictItemService.list(queryChildWrapper);
        List<SysDictItemVO> resultList = Lists.newArrayList();

        if (CollectionUtils.isEmpty(allDict)) {
            return ResponseResult.success(resultList);
        }
        List<SysDictItemVO> natureList = allDict.stream().filter(dept -> DeletedEnum.NATURE.code.equals(dept.getXtZxbz()))
                .map(dept -> BeanUtil.copyProperties(dept, SysDictItemVO.class)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(natureList)) {
            // 递归组织组织机构树
            wrapChildList(sysDictItemVO, natureList);
        }
        return ResponseResult.success(sysDictItemVO.getItemList());
    }

    /**
     * 递归组装字典信息
     *
     * @param sysDictItemVO 字典明细信息
     * @param natureList    所有字典信息
     */
    public void wrapChildList(SysDictItemVO sysDictItemVO, List<SysDictItemVO> natureList) {
        Long rootId = sysDictItemVO.getId();
        List<SysDictItemVO> collect = natureList.stream().filter(dept -> rootId.equals(dept.getZdId()))
                .sorted(Comparator.comparing(SysDictItemVO::getPx).reversed()).collect(Collectors.toList());
        sysDictItemVO.setItemList(collect);
        if (CollectionUtils.isNotEmpty(collect)) {
            collect.forEach(dictItem -> wrapChildList(dictItem, natureList));
        }
    }

    /**
     * 检查并获取字典明细信息
     *
     * @param dictItemCode 字典明细编码
     */
    private SysDictItem checkAndGetItem(String dictItemCode) {
        Asserts.check(StringUtils.isBlank(dictItemCode), "查询的字典明细编码不能为空！");
        QueryWrapper<SysDictItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("zdbh", dictItemCode);
        SysDictItem sysDictItem = sysDictItemService.getOne(queryWrapper);
        Asserts.check(sysDictItem == null || DeletedEnum.DELETED.code.equals(sysDictItem.getXtZxbz()),
                "字典编码对应的字典不存在或已删除");
        return sysDictItem;
    }

    /**
     * 添加字典明细信息
     *
     * @param addDictItemVo 字典明细信息对象
     * @return 添加结果
     */
    @JwtSysUser
    @PostMapping("addSysDictItem")
    @Log(title = "字典明细功能", businessType = BusinessType.INSERT)
    @ApiOperation(value = "添加字典明细信息", httpMethod = "POST", response = Boolean.class)
    public ResponseResult<Boolean> addSysDictItem(@RequestBody @Valid AddDictItemVO addDictItemVo,
                                                  HttpServletRequest servletRequest) {
        Long parentId = addDictItemVo.getParentId();
        SysDict sysDict = sysDictService.getById(parentId);
        String rootPath = null;
        if (sysDict == null) {
            SysDictItem sysDictItem = sysDictItemService.getById(parentId);
            Asserts.check(sysDictItem == null, "传入的父id对应的字典信息不存在");
            rootPath = sysDictItem.getRootPath() + "_";
            addDictItemVo.setZdbh(sysDictItem.getZdbh());
        } else {
            rootPath = sysDict.getId() + "_";
            addDictItemVo.setZdbh(sysDict.getZdbh());
        }

        //拼音
        addDictItemVo.setPy(ChineseCharacterUtil.getUpperCase(addDictItemVo.getZdmc(), false));
        // 获取ip地址
        String ipAddress = IpUtil.getIpAddress(servletRequest);
        sysDictItemService.addSysDictItem(addDictItemVo, rootPath, ipAddress);

        return ResponseResult.success(Boolean.TRUE);
    }


    @GetMapping("selectPage")
    @ApiOperation(value = "", httpMethod = "GET", response = SysDictVO.class)
    public ResponseResult<IPage<SysDictItem>> selectPageDict(SysDictQueryPage vo) {
        Asserts.check(StringUtils.isBlank(vo.getDictCode()), "查询的字典编号不能为空！");
        LambdaQueryWrapper<SysDictItem> wrapper = new LambdaQueryWrapper<SysDictItem>()
                .like(StringUtils.isNotBlank(vo.getZdmc()), SysDictItem::getZdmc, vo.getZdmc())
                .eq(StringUtils.isNotBlank(vo.getDictCode()), SysDictItem::getZdbh, vo.getDictCode())
                .eq(SysDictItem::getXtZxbz, "0");
        return ResponseResult.success(this.sysDictItemService.page(vo, wrapper));
    }

    /**
     * 修改字典明细信息
     *
     * @param editDictItemVO 字典对象
     * @return 修改结果
     */
    @JwtSysUser
    @PostMapping("updateSysDictItem")
    @Log(title = "字典明细功能", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "修改字典明细信息", httpMethod = "POST", response = Boolean.class)
    public ResponseResult<Boolean> updateSysDictItem(@RequestBody @Valid EditDictItemVO editDictItemVO,
                                                     HttpServletRequest servletRequest) {
        Asserts.check(editDictItemVO.getId() == null, "主键id不能为空！");
        SysDictItem oldSysDictItem = sysDictItemService.getBaseMapper().selectById(editDictItemVO.getId());
        Asserts.check(oldSysDictItem == null, "主键为 %s 的字典明细信息不存在", editDictItemVO.getId());

        // 获取ip地址
        String ipAddress = IpUtil.getIpAddress(servletRequest);

        UserInfo userInfo = UserInfoManager.get();
        Asserts.checkAuth(userInfo == null, "用户信息为空，请登陆");
        oldSysDictItem.setXtZhxgsj(new Date());
        oldSysDictItem.setXtZhxgrid(userInfo.getUserId().toString());
        oldSysDictItem.setXtZhxgrxm(userInfo.getUserName());
        oldSysDictItem.setXtZhxgrbmid(userInfo.getDeptId().toString());
        oldSysDictItem.setXtZhxgrbm(userInfo.getDeptName());
        oldSysDictItem.setXtZhxgip(ipAddress);

        oldSysDictItem.setBz(editDictItemVO.getBz());
        oldSysDictItem.setDm(editDictItemVO.getDm());
        oldSysDictItem.setPy(editDictItemVO.getPy());
        oldSysDictItem.setPx(editDictItemVO.getPx());
        oldSysDictItem.setZdbh(editDictItemVO.getZdbh());
        oldSysDictItem.setZdmc(editDictItemVO.getZdmc());
        oldSysDictItem.setPy(ChineseCharacterUtil.getUpperCase(oldSysDictItem.getZdmc(), false));
        int i = sysDictItemService.getBaseMapper().updateById(oldSysDictItem);
        if (i > 0) {
            List<SysDictItem> dictDatas = this.sysDictItemService.getBaseMapper().selectList(new LambdaQueryWrapper<SysDictItem>()
                    .eq(SysDictItem::getXtZxbz, 0)
                    .eq(SysDictItem::getZdbh, oldSysDictItem.getZdbh())
            );
            DictUtils.setDictCache(oldSysDictItem.getZdbh(), dictDatas);
        }
        return ResponseResult.success(Boolean.TRUE);
    }

    /**
     * 修改字典明细信息
     *
     * @param deleteVO 字典主键
     * @return 删除结果
     */
    @JwtSysUser
    @PostMapping("deleteSysDictItem")
    @Log(title = "字典明细功能", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除字典明细信息", httpMethod = "POST", response = Boolean.class)
    public ResponseResult<Boolean> deleteSysDictItem(@RequestBody DeleteVO deleteVO, HttpServletRequest servletRequest) {
        SysDictItem sysDictItem = sysDictItemService.getBaseMapper().selectById(deleteVO.getId());
        Asserts.check(sysDictItem == null, "主键为 %s 的字典明细信息不存在", deleteVO.getId());

        QueryWrapper<SysDictItem> childQuery = new QueryWrapper<>();
        childQuery.and(wrapper -> wrapper.eq("zd_id", sysDictItem.getId()));
        childQuery.and(wrapper -> wrapper.eq("xt_zxbz", DeletedEnum.NATURE.code));
        List<SysDictItem> list = sysDictItemService.list(childQuery);
        Asserts.check(CollectionUtils.isNotEmpty(list), "当前节点下有子节点，请先删除子节点！");

        sysDictItem.setXtZxbz(DeletedEnum.DELETED.code);
        sysDictItem.setXtZxyy(deleteVO.getZxyy());

        // 获取ip地址
        String ipAddress = IpUtil.getIpAddress(servletRequest);

        UserInfo userInfo = UserInfoManager.get();
        Asserts.checkAuth(userInfo == null, "用户信息为空，请登陆");
        sysDictItem.setXtZhxgsj(new Date());
        sysDictItem.setXtZhxgrid(userInfo.getUserId().toString());
        sysDictItem.setXtZhxgrxm(userInfo.getUserName());
        sysDictItem.setXtZhxgrbmid(userInfo.getDeptId().toString());
        sysDictItem.setXtZhxgrbm(userInfo.getDeptName());
        sysDictItem.setXtZhxgip(ipAddress);
        int i = sysDictItemService.getBaseMapper().updateById(sysDictItem);
        if (i > 0) {
            List<SysDictItem> dictDatas = this.sysDictItemService.getBaseMapper().selectList(new LambdaQueryWrapper<SysDictItem>()
                    .eq(SysDictItem::getXtZxbz, 0)
                    .eq(SysDictItem::getZdbh, sysDictItem.getZdbh())
            );
            DictUtils.setDictCache(sysDictItem.getZdbh(), dictDatas);
        }

        return ResponseResult.success(Boolean.TRUE);
    }


    @JwtSysUser
    @PostMapping("deleteSysDictItemBatch")
    @Log(title = "字典明细功能", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除字典明细信息", httpMethod = "POST", response = Boolean.class)
    public ResponseResult<Boolean> deleteSysDictItemBatch(@RequestBody List<Long> ids, HttpServletRequest servletRequest) {

        if (!CollectionUtils.isEmpty(ids)) {
            for (Long id : ids) {
                SysDictItem sysDictItem = sysDictItemService.getBaseMapper().selectById(id);
                Asserts.check(sysDictItem == null, "主键为 %s 的字典明细信息不存在", id);

                QueryWrapper<SysDictItem> childQuery = new QueryWrapper<>();
                childQuery.and(wrapper -> wrapper.eq("zd_id", sysDictItem.getId()));
                childQuery.and(wrapper -> wrapper.eq("xt_zxbz", DeletedEnum.NATURE.code));
                List<SysDictItem> list = sysDictItemService.list(childQuery);
                Asserts.check(CollectionUtils.isNotEmpty(list), "当前节点下有子节点，请先删除子节点！");

                sysDictItem.setXtZxbz(DeletedEnum.DELETED.code);
                sysDictItem.setXtZxyy(null);
                // 获取ip地址
                String ipAddress = IpUtil.getIpAddress(servletRequest);
                UserInfo userInfo = UserInfoManager.get();
                Asserts.checkAuth(userInfo == null, "用户信息为空，请登陆");
                sysDictItem.setXtZhxgsj(new Date());
                sysDictItem.setXtZhxgrid(userInfo.getUserId().toString());
                sysDictItem.setXtZhxgrxm(userInfo.getUserName());
                sysDictItem.setXtZhxgrbmid(userInfo.getDeptId().toString());
                sysDictItem.setXtZhxgrbm(userInfo.getDeptName());
                sysDictItem.setXtZhxgip(ipAddress);
                int i = sysDictItemService.getBaseMapper().updateById(sysDictItem);
                if (i > 0) {
                    List<SysDictItem> dictDatas = this.sysDictItemService.getBaseMapper().selectList(new LambdaQueryWrapper<SysDictItem>()
                            .eq(SysDictItem::getXtZxbz, 0)
                            .eq(SysDictItem::getZdbh, sysDictItem.getZdbh())
                    );
                    DictUtils.setDictCache(sysDictItem.getZdbh(), dictDatas);
                }
            }
        }
        return ResponseResult.success(Boolean.TRUE);
    }
}

