/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.manager.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.*;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.springblade.common.utils.SnowFlakeUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.mp.utils.PageUtil;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.manager.dto.FindAllUserByConditionDTO;
import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
import org.springblade.manager.dto.WbsTreeContractDTO;
import org.springblade.manager.entity.WbsTreeContract;
import org.springblade.manager.mapper.SaveUserInfoByProjectMapper;
import org.springblade.manager.service.IWbsTreeContractService;
import org.springblade.manager.service.SaveUserInfoByProjectService;
import org.springblade.manager.vo.*;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.feign.IUserClient;
import org.springblade.system.user.vo.UserVO2;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;

import org.springblade.manager.entity.ContractInfo;
import org.springblade.manager.wrapper.ContractInfoWrapper;
import org.springblade.manager.service.IContractInfoService;
import org.springblade.core.boot.ctrl.BladeController;
import sun.security.provider.MD5;
import sun.security.provider.SHA;

import java.util.*;

/**
 * 合同段信息表 控制器
 *
 * @author liuyc
 * @since 2022-04-14
 */
@RestController
@AllArgsConstructor
@RequestMapping("/contractInfo")
@Api(value = "合同段", tags = "合同段接口")
public class ContractInfoController extends BladeController {

    private final IContractInfoService contractInfoService;
    private final SaveUserInfoByProjectService saveUserInfoByProject;
    private final IUserClient iUserClient;
    private final IWbsTreeContractService wbsTreeContractService;
    private final SaveUserInfoByProjectMapper saveUserInfoByProjectMapper;

    /**
     * 详情
     */
    @GetMapping("/detail")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "传入contractInfo")
    public R<ContractInfoVO> detail(ContractInfo contractInfo) {
        ContractInfo detail = contractInfoService.getOne(Condition.getQueryWrapper(contractInfo));
        return R.data(ContractInfoWrapper.build().entityVO(detail));
    }

    /**
     * 详情
     */
    @GetMapping("/detail2")
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "详情", notes = "传入contractInfo")
    public R<ContractInfoVO2> detail2(ContractInfo contractInfo) {
        ContractInfoVO2 detail = contractInfoService.selectByCondition(contractInfo);
        return R.data(detail);
    }

    /**
     * 根据项目id查询当前所有合同
     */
    @GetMapping("/findContractInfoByPid")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "根据项目id查询当前所有合同", notes = "传入pid")
    public R<List<ContractInfo>> findContractInfoByPid(String pid) {
        List<ContractInfo> contractInfoVOS = contractInfoService.selectContractInfoPageByPid(pid);
        return R.data(contractInfoVOS);
    }

    /**
     * 分页 合同段信息表
     */
    @GetMapping("/list")
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "分页", notes = "传入contractInfo")
    public R<IPage<ContractInfoVO>> list(ContractInfo contractInfo, Query query) {
        IPage<ContractInfo> pages = contractInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(contractInfo));
        return R.data(ContractInfoWrapper.build().pageVO(pages));
    }

    /**
     * 自定义分页 合同段信息表
     */
    @GetMapping("/page")
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "自定义分页", notes = "传入contractInfo")
    public R<IPage<ContractInfoVO>> page(ContractInfoVO contractInfo, Query query) {
        IPage<ContractInfoVO> pages = contractInfoService.selectContractInfoPage(Condition.getPage(query), contractInfo);
        return R.data(pages);
    }


    /**
     * 新增 合同段信息表
     */
    @PostMapping("/save")
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "新增", notes = "传入contractInfo")
    public R save(@Valid @RequestBody ContractInfo contractInfo) {
        return R.status(contractInfoService.save(contractInfo));
    }

    /**
     * 修改 合同段信息表
     */
    @PostMapping("/update")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "修改", notes = "传入contractInfo")
    public R update(@Valid @RequestBody ContractInfo contractInfo) {
        return R.status(contractInfoService.updateById(contractInfo));
    }

    /**
     * 删除文件
     */
    @GetMapping("/deleteFile")
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "删除文件", notes = "传入文件url")
    public R deleteFile(@Valid @RequestParam("url") String url) {
        return R.status(contractInfoService.deleteFile(url));
    }


    /**
     * 新增或修改 合同段信息表
     */
    @PostMapping("/submit")
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新增或修改", notes = "传入contractInfo")
    public R submit(@Valid @RequestBody ContractInfoVO contractInfo) {
        boolean b = contractInfoService.saveAndUpdateContract(contractInfo);
        if (b) {
            return R.data(contractInfo, "操作成功");
        }
        return R.fail("操作失败");
    }


    /**
     * 删除 合同段信息表
     */
    @PostMapping("/remove")
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "逻辑删除", notes = "传入ids")
    public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
        List<WbsTreeContract> wbsTreeContracts = wbsTreeContractService.findWbsTreeContract(ids);
        if (wbsTreeContracts.size() > 0) {
            return R.fail("合同段存在关联的WBS树,删除失败");
        }
        return R.status(contractInfoService.deleteLogic(Func.toLongList(ids)));
    }


    /**
     * 查询角色的岗位
     */
    @GetMapping("/findJobByRoleId")
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "查询角色下的岗位", notes = "传入id")
    public R<List<CRolePostVO>> findJobByRoleId(@ApiParam(value = "id", required = true)
                                                @RequestParam("id") String id) {
        List<CRolePostVO> list = contractInfoService.findJobByRoleId(id);
        if (list.size() <= 0) {
            return R.data(list, "未查询到信息");
        }
        return R.data(list);
    }


    /**
     * 根据用户列表
     */
    @GetMapping("/findUserList")
    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "", notes = "")
    public R<List<User>> findUserList(){
        List<User> user = contractInfoService.findUserList();
        if (user.size() > 0) {
            return R.data(user);
        }
        return R.success("未查询到信息");
    }


    /**
     * 根据项目id、合同id、角色id查询当前运维的用户
     */
    @GetMapping("/findUserListByCondition")
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "查询当前项目角色下的运维用户列表", notes = "传入项目id、角色id、合同id(非必传)、size每页数量、current当前页")
    public R<IPage<User>> findUserListByCondition(FindAllUserByConditionDTO values, Query query) {
        IPage<User> users = contractInfoService.findUserListByCondition(Condition.getPage(query), values);
        return R.data(users);
    }


    /**
     * 项目分配用户批量保存-项目分配维护人员
     */
    @PostMapping("/saveUserInfoByProject")
    @ApiOperationSupport(order = 12)
    @ApiOperation(value = "保存-项目分配维护人员", notes = "传入项目id、合同id、字典主键id、用户id List集合")
    public R saveUserInfoByProject(@RequestBody List<SaveUserInfoByProjectDTO> list) {
        if (list.size() > 0) {
            list.forEach((lists) -> {
                Long row = saveUserInfoByProjectMapper.selectCount(
                        Wrappers.<SaveUserInfoByProjectDTO>query().lambda().
                                eq(SaveUserInfoByProjectDTO::getProjectId, lists.getProjectId()).
                                eq(SaveUserInfoByProjectDTO::getContractId, lists.getContractId()).
                                eq(SaveUserInfoByProjectDTO::getRoleId, lists.getRoleId()).
                                eq(SaveUserInfoByProjectDTO::getUserId, lists.getUserId()));
                if (row > 0L) {
                    throw new ServiceException("当前用户角色已存在该合同段,请重新选择");
                }
                if (StringUtils.isEmpty(lists.getContractId())) {
                    //全部
                    List<ContractInfo> contractInfos = contractInfoService.selectContractInfoPageByPid(lists.getProjectId());
                    if (contractInfos.size() <= 0) {
                        //无合同段-分配角色
                        Long row2 = saveUserInfoByProjectMapper.selectCount(
                                Wrappers.<SaveUserInfoByProjectDTO>query().lambda().
                                        eq(SaveUserInfoByProjectDTO::getProjectId, lists.getProjectId()).
                                        eq(SaveUserInfoByProjectDTO::getRoleId, lists.getRoleId()).
                                        eq(SaveUserInfoByProjectDTO::getUserId, lists.getUserId()));
                        if (row2 > 0L) {
                            throw new ServiceException("当前用户已存在,请重新选择");
                        }
                        Long id = SnowFlakeUtil.getId();
                        lists.setId(id);
                        lists.setStatus(1);
                        saveUserInfoByProject.save(lists);
                    } else {
                        contractInfos.forEach(contractInfo -> {
                            Long row1 = saveUserInfoByProjectMapper.selectCount(
                                    Wrappers.<SaveUserInfoByProjectDTO>query().lambda().
                                            eq(SaveUserInfoByProjectDTO::getProjectId, lists.getProjectId()).
                                            eq(SaveUserInfoByProjectDTO::getContractId, contractInfo.getId()).
                                            eq(SaveUserInfoByProjectDTO::getRoleId, lists.getRoleId()).
                                            eq(SaveUserInfoByProjectDTO::getUserId, lists.getUserId()));
                            if (row1 > 0L) {
                                throw new ServiceException("当前用户角色已在合同段下存在,请重新选择");
                            }
                            Long id = SnowFlakeUtil.getId();
                            lists.setId(id);
                            lists.setStatus(1);
                            lists.setContractId(String.valueOf(contractInfo.getId()));
                            saveUserInfoByProject.save(lists);
                        });
                    }
                } else {
                    //单合同段
                    saveUserInfoByProject.saveBatch(list);
                }
            });
            return R.success("保存成功");
        }
        return R.fail("保存失败");
    }

    /**
     * 根据项目id、合同id、岗位id查询当前分配的用户-查询当前项目合同岗位下的用户
     */
    @GetMapping("/findAllUserByCondition")
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "查询当前项目合同岗位下的用户", notes = "传入项目id、合同id、岗位id、size每页数量、current当前页")
    public R<IPage<UserVO2>> findAllUserByCondition(FindAllUserByConditionDTO values, Query query) {
        IPage<UserVO2> users = contractInfoService.findAllUserByCondition(Condition.getPage(query), values);
        return R.data(users);
    }


    /**
     * 项目分配用户批量保存-项目合同分配人员
     */
    @PostMapping("/saveUserInfoByProjectTow")
    @ApiOperationSupport(order = 13)
    @ApiOperation(value = "保存-项目合同分配人员", notes = "传入项目id、合同id、岗位处roleId、用户id")
    @Transactional(rollbackFor = Exception.class)
    public R saveUserInfoByProjectTow(@RequestBody List<SaveUserInfoByProjectDTO> list) {
        if (list.size() > 0) {
            //判重
            list.forEach((lists) -> {
                Long row = saveUserInfoByProjectMapper.selectCount(
                        Wrappers.<SaveUserInfoByProjectDTO>query().lambda().
                                eq(SaveUserInfoByProjectDTO::getProjectId, lists.getProjectId()).
                                eq(SaveUserInfoByProjectDTO::getContractId, lists.getContractId()).
                                //eq(SaveUserInfoByProjectDTO::getRoleId, lists.getRoleId()).
                                        eq(SaveUserInfoByProjectDTO::getUserId, lists.getUserId()));
                if (row > 0L) {
                    throw new ServiceException("当前用户类型已存在合同段,请重新选择项目合同段添加");
                }
            });
            //添加User-roleId字段
            iUserClient.updateUserRoleId(list);
            boolean result = saveUserInfoByProject.saveBatch(list);
            if (result) {
                return R.success("保存成功");
            }
        }
        return R.fail("保存失败");
    }


    /**
     * 项目分配用户逻辑删除
     */
    @PostMapping("/removeUsersByIds")
    @ApiOperationSupport(order = 14)
    @ApiOperation(value = "逻辑删除", notes = "传入当前列表用户的记录ids")
    @Transactional(rollbackFor = Exception.class)
    public R removeUsersByIds(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
        if (StringUtils.isEmpty(ids)) {
            throw new ServiceException("请选择要删除的数据");
        } else if (Func.toLongList(ids).size() > 1) {
            // TODO 未设定批量删除
            throw new ServiceException("功能未开放");
        }
        //用户关联信息
        SaveUserInfoByProjectDTO saveUserInfoByProjectDTO = saveUserInfoByProjectMapper.selectById(ids);
        String userId = saveUserInfoByProjectDTO.getUserId();
        String roleId = saveUserInfoByProjectDTO.getRoleId();
        //删除当前用户RoleId
        iUserClient.updateUserRoleIdTwo(userId, roleId);
        return R.status(saveUserInfoByProject.deleteLogic(Func.toLongList(ids)));
    }

    /**
     * 重置密码
     */
    @PostMapping("/resetPasswordByUserId")
    @ApiOperationSupport(order = 15)
    @ApiOperation(value = "重置密码", notes = "传入当前用户的userId，默认重置密码123456")
    public R updatePasswordByUserId(@ApiParam(value = "用户userId", required = true) @RequestParam String userId) {
        if (StringUtils.isNotEmpty(userId)) {
            return iUserClient.resetPassword(userId);
        }
        return R.fail("操作失败");
    }


    /**
     * 分配合同段wbs节点树保存或者修改
     */
    @PostMapping("/submitWbsTreeInContract")
    @ApiOperationSupport(order = 16)
    @ApiOperation(value = "分配合同段wbs节点树保存或修改", notes = "传入ids,wbsId,项目id,合同段id")
    public R submitWbsTreeInContract(@RequestBody WbsTreeContractDTO wbsTreeContractDTO) {
        boolean b = wbsTreeContractService.submitWbsTreeInContract(wbsTreeContractDTO);
        if (b) {
            return R.success("关联合同段树成功");
        }
        return R.fail("关联合同段树失败");
    }

    /**
     * 查询合同段私有Wbs节点树形结构
     */
    @GetMapping("/tree")
    @ApiOperationSupport(order = 17)
    @ApiOperation(value = "查询合同段私有Wbs节点树形结构", notes = "传入wbsId,项目id,合同段id")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "wbsId", value = "wbsId", required = true),
            @ApiImplicitParam(name = "项目id", value = "projectId", required = true),
            @ApiImplicitParam(name = "合同段id", value = "contractId", required = true)
    })
    public R tree(String wbsId, String projectId, String contractId) {
        List<WbsTreeContractTreeVO> tree = contractInfoService.tree(wbsId, projectId, contractId);
        if (tree != null && tree.size() > 0) {
            return R.data(tree);
        }
        return R.fail(200, "未查询到信息");
    }


    /**
     * 查询所有施工合同wbs树根节点(新建监理或业主合同段时，加载当前项目下的施工WBS树，分配时使用)
     */
    @GetMapping("/treeAllConstruction")
    @ApiOperationSupport(order = 18)
    @ApiOperation(value = "查询所有施工合同wbs树根节点", notes = "传入wbsId,项目id")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "项目id", value = "projectId", required = true)
    })
    public R treeAllConstruction(String projectId) {
        List<WbsTreeContractVO2> tree = contractInfoService.treeTwo(projectId);
        if (tree != null && tree.size() > 0) {
            return R.data(tree);
        }
        return R.fail(200, "未查询到信息");
    }


    /**
     * 懒加载合同wbs节点树形结构
     */
    @GetMapping("/lazy-tree")
    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "懒加载合同段wbs节点树形结构", notes = "传入wbsId，parentId，请求头token")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "parentId", value = "父级parentId = primaryKeyId , 根节点=0", required = true),
            @ApiImplicitParam(name = "contractId", value = "合同段id", required = true),
            @ApiImplicitParam(name = "contractIdRelation", value = "合同段关联id，监理、业主合同树懒加载子级必传")
    })
    public R<List<WbsTreeContractTreeVO>> lazyTree(Long parentId, String contractId, String contractIdRelation) {
        ContractInfo contractInfo = contractInfoService.selectById(contractId);
        if (contractInfo == null) {
            throw new ServiceException("合同段类型不存在");
        }
        List<WbsTreeContractTreeVO> tree = wbsTreeContractService.lazyTreeTwo(contractIdRelation, parentId, contractInfo.getContractType(), contractId);
        if (tree != null && tree.size() > 0) {
            return R.data(tree);
        }
        return R.fail(200, "未查询到信息");
    }

}
