/*
 *      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 com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.*;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;
import javax.validation.Valid;

import org.springblade.common.utils.SnowFlakeUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
import org.springblade.manager.entity.ContractInfo;
import org.springblade.manager.entity.ProjectInfo;
import org.springblade.manager.entity.SignPfxDeputy;
import org.springblade.manager.service.*;
import org.springblade.manager.vo.*;
import org.springblade.system.entity.Role;
import org.springblade.system.feign.ISysClient;
import org.springblade.system.user.entity.User;
import org.springblade.system.vo.RoleVO;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestParam;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.manager.entity.SignPfxFile;
import org.springblade.core.boot.ctrl.BladeController;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 个人/企业证书信息表 控制器
 *
 * @author BladeX
 * @since 2022-06-24
 */
@RestController
@AllArgsConstructor
@RequestMapping("/signPfxFile")
@Api(value = "个人、企业证书信息表", tags = "个人、企业证书信息表接口")
public class SignPfxFileController extends BladeController {

	private final ISignPfxFileService signPfxFileService;

	private final IProjectInfoService projectInfoService;

	private final IContractInfoService contractInfoService;

	private final SaveUserInfoByProjectService saveUserInfoByProjectService;

	private final ISysClient sysClient;

	private final ISignPfxDeputyService signPfxDeputyService;

	/**
	 * 获取当前系统下分配的一级角色
	 * @return 结果
	 */
	@GetMapping("/queryRole")
	@ApiOperationSupport(order = 12)
	@ApiOperation(value = "获取当前系统下分配的一级角色")
	public R<List<RoleVO>> queryRole(){
		 return R.data(this.sysClient.search().getData());
	}

	/**
	 * 获取当前系统下所有用户
	 * @return 结果
	 */
	@GetMapping("/findUserByName")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "获取当前系统下所有用户")
	public R<List<User>> findUserByName(){
		return R.data(this.contractInfoService.findUserByName(""));
	}


	/**
	 * 获取当前项目及其所有合同段
	 * @return 项目及合同段列表
	 */
	@GetMapping("/queryProjectAndContract")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "获取当前项目及其所有合同段")
	public R<List<ProjectInfoVO>> queryProjectAndContract(){
		//结果集合
		List<ProjectInfoVO> result = new ArrayList<>();

		//获取项目列表
		List<ProjectInfo> projectResult = this.projectInfoService.list(Wrappers.<ProjectInfo>lambdaQuery().eq(ProjectInfo::getIsDeleted, 0));
		if(projectResult != null && projectResult.size() > 0){
			String projectIds = String.join(",", JSONArray.parseArray(JSONObject.toJSONString(projectResult.stream().map(ProjectInfo::getId).distinct().collect(Collectors.toList())), String.class));
			//获取合同段
			List<ContractInfo> contractInfos = this.contractInfoService.findContractInProject(projectIds);
			if(contractInfos != null && contractInfos.size() > 0){
				//转换实体
				result = JSONArray.parseArray(JSONObject.toJSONString(projectResult), ProjectInfoVO.class);
				List<ContractInfoVO> contractInfoVOS = JSONArray.parseArray(JSONObject.toJSONString(contractInfos), ContractInfoVO.class);
				//设置合同段信息
				result.forEach(project -> {
					project.setName(project.getProjectName());
					//获取合同段
					Iterator<ContractInfoVO> iterator = contractInfoVOS.iterator();
					while (iterator.hasNext()){
						ContractInfoVO next = iterator.next();
						next.setName(next.getContractName());
						if(project.getId().toString().equals(next.getPId())){
							project.getContractInfoList().add(next);
							iterator.remove();
						}
					}
				});
			}
		}

		return R.data(result);
	}

	/**
	 * 获取系统所有角色划分
	 */
	@GetMapping("/queryAllRoleList")
	@ApiOperationSupport(order = 9)
	@ApiOperation(value = "获取系统所有角色划分")
	public R<List<RoleSignPfxUserVO>> queryAllRoleList(@RequestParam String contractId){
		//获取当前系统配置的角色划分
		List<RoleVO> roleVOS = this.sysClient.search().getData();
		//获取项目人员
		List<SaveUserInfoByProjectDTO> contractUserList = this.saveUserInfoByProjectService.list(Wrappers.<SaveUserInfoByProjectDTO>lambdaQuery().eq(SaveUserInfoByProjectDTO::getContractId, contractId).eq(SaveUserInfoByProjectDTO::getIsDeleted, 0));

		//返回结果
		List<RoleSignPfxUserVO> result = new ArrayList<>();
		//企业章
//		RoleSignPfxUserVO pfxUnitVo = new RoleSignPfxUserVO();
//		pfxUnitVo.setRoleId(1L);
//		pfxUnitVo.setRoleName("单位证书");
//		List<SignPfxFile> unitPfxList = this.signPfxFileService.list(Wrappers.<SignPfxFile>lambdaQuery().eq(SignPfxFile::getContractId, contractId).eq(SignPfxFile::getIsDeleted, 0));
//		if(unitPfxList != null && unitPfxList.size() > 0){
//			pfxUnitVo.setSignPfxFileList(unitPfxList);
//		}
//		result.add(pfxUnitVo);

		//循环角色，对项目人员进行分组
		for(RoleVO vo : roleVOS){
			//设置实体
			RoleSignPfxUserVO pfxUserVo = new RoleSignPfxUserVO();
			pfxUserVo.setRoleId(vo.getId());
			pfxUserVo.setRoleName(vo.getRoleName());

			//处理子节点
			List<RoleVO> childRoles =  vo.getChildren();
			if(childRoles != null && childRoles.size() > 0){
				for(RoleVO childVo : childRoles){
					//设置实体
					RoleSignPfxUserVO childPfxUserVo = new RoleSignPfxUserVO();
					childPfxUserVo.setRoleId(childVo.getId());
					childPfxUserVo.setRoleName(childVo.getRoleName());

					//循环项目人员，获取个人证书，如果没有个人证书则删除
					Iterator<SaveUserInfoByProjectDTO> iterator = contractUserList.iterator();
					while (iterator.hasNext()){
						SaveUserInfoByProjectDTO next = iterator.next();

						if(next.getRoleId().equals(childVo.getId().toString())){
							//角色相符
							SignPfxFile userSignPfx = this.signPfxFileService.getOne(Wrappers.<SignPfxFile>lambdaQuery().eq(SignPfxFile::getCertificateUserId, next.getUserId()));
							if(userSignPfx == null){
								iterator.remove();
								continue;
							}
							//存在证书则设置进结果对象的证书集合中
							childPfxUserVo.getSignPfxFileList().add(userSignPfx);
						}
					}
					//设置子集
					pfxUserVo.getChildRoleList().add(childPfxUserVo);
				}
			}

			//设置结果
			result.add(pfxUserVo);
		}

		return R.data(result);
	}

	/**
	 * 获取所有有效项目
	 */
	@GetMapping("/queryProjectList")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "获取所有有效项目")
	public R<List<ProjectInfo>> queryProjectList(){
		return R.data(this.projectInfoService.list(Wrappers.<ProjectInfo>lambdaQuery().eq(ProjectInfo::getIsDeleted, 0)));
	}

	/**
	 * 证书管理分页
	 */
	@GetMapping("/singPfxManagementPage")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "证书管理分页")
	@ApiImplicitParam(name = "vo", value = "必传current、size, 选传projectId")
	public R<IPage<SingPfxManagementVO>> singPfxManagementPage(@RequestParam Integer current, @RequestParam Integer size, @RequestParam Long contractId){
		SingPfxManagementVO vo = new SingPfxManagementVO();
		vo.setCurrent(current);
		vo.setSize(size);
		vo.setContractId(contractId);

		Query query = new Query();
		query.setSize(vo.getSize());
		query.setCurrent(vo.getCurrent());

		return R.data(this.signPfxFileService.singPfxManagementPage(Condition.getPage(query), vo));
	}

	/**
	 * 详情
	 */
	@PostMapping("/getById")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "获取详情数据")
	@ApiImplicitParam(name = "id", value = "列表数据主键ID", required = true)
	public R<SignPfxFileVO> getById(Long id){
		//查询数据
		SignPfxFile data = this.signPfxFileService.getById(id);
		//实体转换
		SignPfxFileVO vo = JSONObject.parseObject(JSONObject.toJSONString(data), SignPfxFileVO.class);
		List<SignPfxDeputy> deputies = this.signPfxDeputyService.list(Wrappers.<SignPfxDeputy>lambdaQuery().eq(SignPfxDeputy::getSignPfxFileId, id).eq(SignPfxDeputy::getIsDeleted, 0));
		vo.setSignPfxDeputieList(deputies);

		return R.data(vo);
	}

	/**
	 * 注册证书
	 * @return 结果
	 */
	@PostMapping("/goRegister")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "注册(先对接接口，功能未完成)")
	@ApiImplicitParam(name = "id", value = "列表数据主键ID", required = true)
	public R<Boolean> goRegister(Long id){
		return this.signPfxFileService.goRegister(id);
	}

	/**
	 * 自定义分页 个人/企业证书信息表
	 */
	@GetMapping("/page")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "分页")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "current", value = "当前页", required = true),
			@ApiImplicitParam(name = "size", value = "当前页数量", required = true)
	})
	public R<IPage<SignPfxFileVO>> page(SignPfxFileVO vo) {
		Query query = new Query();
		query.setSize(vo.getSize());
		query.setCurrent(vo.getCurrent());

		IPage<SignPfxFileVO> pages = this.signPfxFileService.selectSignPfxFilePage(Condition.getPage(query), vo);
		return R.data(pages);
	}

	/**
	 * 新增 个人/企业证书信息表
	 */
	@PostMapping("/save")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "新增", notes = "传入signPfxFile")
	public R save(@Valid @RequestBody SignPfxFileVO vo) {

		if(new Integer("2").equals(vo.getCertificateType())){
			this.saveSignPfxDeputy(vo);
		}

		return R.status(this.signPfxFileService.save(vo));
	}

	/**
	 * 修改 个人/企业证书信息表
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "修改", notes = "传入signPfxFile")
	public R update(@Valid @RequestBody SignPfxFileVO vo) {
		if(new Integer("2").equals(vo.getCertificateType())){
			//查询旧数据
			SignPfxFile oldData = this.signPfxFileService.getById(vo.getId());
			if(!vo.getProjectContractRole().trim().equals(oldData.getProjectContractRole().trim())){
				//如果不匹配，先删除
				this.signPfxDeputyService.update(Wrappers.<SignPfxDeputy>lambdaUpdate().set(SignPfxDeputy::getIsDeleted, 1).eq(SignPfxDeputy::getSignPfxFileId, vo.getId()));
				//再重新生成
				this.saveSignPfxDeputy(vo);
			}
		}
		return R.status(this.signPfxFileService.updateById(vo));
	}

	private void saveSignPfxDeputy(SignPfxFileVO vo){
		String[] projectContractRoles = vo.getProjectContractRole().trim().split(",");
		//从表数据
		List<SignPfxDeputy> insertList = new ArrayList<>();
		vo.setId(SnowFlakeUtil.getId());
		for(String projectContractRole : projectContractRoles){
			String[] array = projectContractRole.split("-");
			//查询项目信息
			ProjectInfo projectInfo = this.projectInfoService.getById(array[0]);
			//获取合同段ID
			ContractInfo contractInfo = this.contractInfoService.getById(array[1]);
			//获取角色
			Role role = this.sysClient.getRole(Long.parseLong(array[2])).getData();

			//新增从表数据
			SignPfxDeputy signPfxDeputy = new SignPfxDeputy();
			signPfxDeputy.setSignPfxFileId(vo.getId());
			signPfxDeputy.setProjectId(projectInfo.getId());
			signPfxDeputy.setProjectName(projectInfo.getProjectName());
			signPfxDeputy.setContractId(contractInfo.getId());
			signPfxDeputy.setContractName(contractInfo.getContractName());
			signPfxDeputy.setRoleId(role.getId());
			signPfxDeputy.setRoleName(role.getRoleName());

			insertList.add(signPfxDeputy);
		}
		if(insertList.size() > 0){
			this.signPfxDeputyService.saveBatch(insertList);
		}
	}

	/**
	 * 删除 个人/企业证书信息表
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(this.signPfxFileService.deleteLogic(Func.toLongList(ids)));
	}

	
}
