/*
 *      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.finance.controller;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.finance.dto.ParamPushInner;
import org.springblade.finance.entity.InnerAccount;
import org.springblade.finance.entity.InnerBackFile;
import org.springblade.finance.entity.InnerBillAudit;
import org.springblade.finance.entity.InnerBillAuditUser;
import org.springblade.finance.entity.InnerDealDetail;
import org.springblade.finance.enums.AuditStatusEnum;
import org.springblade.finance.service.IInnerAccountService;
import org.springblade.finance.service.IInnerBackFileService;
import org.springblade.finance.service.IInnerBillAuditService;
import org.springblade.finance.service.IInnerBillAuditUserService;
import org.springblade.finance.service.IInnerDealDetailService;
import org.springblade.system.client.UserClient;
import org.springblade.system.client.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * 内部结算-结算单审核表 控制器
 *
 * @author zbc
 * @since 2022-07-20
 */
@RestController
@RequestMapping("finance/innerBillAudit")
@Api(value = "内部结算-结算单审核表", tags = "内部结算-结算单审核表接口")
@Slf4j
public class InnerBillAuditController {

	@Autowired
	private IInnerBillAuditUserService innerBillAuditUserService;

	@Autowired
	private IInnerDealDetailService innerDealDetailService;

	@Autowired
	private IInnerBillAuditService innerBillAuditService;

	@Autowired
	private IInnerAccountService innerAccountService;

	@Autowired
	private IInnerBackFileService innerBackFileService;

	@Autowired
	private UserClient userService;


	/**
	 * 推送内部结算-结算单
	 * @param paramPush
	 * @return
	 */
	@PostMapping("/add")
	@ApiOperation(value = "推送内部结算-结算单")
	public R<String> add(@RequestBody ParamPushInner paramPush){
		LambdaQueryWrapper<InnerBillAudit> queryWrapper = Wrappers.<InnerBillAudit>lambdaQuery()
			.eq(InnerBillAudit::getSid, paramPush.getSid())
			.ne(InnerBillAudit::getAuditstatus, AuditStatusEnum.fin_cancel.getValue());
		int count = innerBillAuditService.count(queryWrapper);
		if(count > 0) {
			return R.fail("结算单已推送，不能重复操作。");
		}

		InnerBillAudit drat = new InnerBillAudit();
		drat.setSid(paramPush.getSid());
		drat.setCreatetime(new Date());
		drat.setCreatebyuserid(SecureUtil.getUserId());
		drat.setCreatebyname(SecureUtil.getNickName());
		if(paramPush.getUserList() != null && !paramPush.getUserList().isEmpty()) {
			drat.setAuditstatus(AuditStatusEnum.wait_check.getValue());
		}else {
			drat.setAuditstatus(AuditStatusEnum.wait_upload.getValue());
		}
		boolean ret = innerBillAuditService.save(drat);
		if(ret) {
			List<InnerBillAuditUser> userList = new ArrayList<InnerBillAuditUser>();
			userList.add(new InnerBillAuditUser(drat.getAid(), SecureUtil.getUserId(), SecureUtil.getNickName(), new Date(), 1));
			if(paramPush.getUserList() != null && !paramPush.getUserList().isEmpty()) {
				paramPush.getUserList().forEach(f -> {
					f.setAid(drat.getAid());
					if(f.getUserid() == 1394115436887109634L){
						f.setCheckstatus(1);
						f.setChecktime(new Date());
					}else {
						f.setCheckstatus(0);
					}
				});
				userList.addAll(paramPush.getUserList());
			}
			List<InnerBillAuditUser> list = sysUser(userList);
			innerBillAuditUserService.saveBatch(list);

			int num = innerBillAuditUserService.count(Wrappers.<InnerBillAuditUser>lambdaQuery().eq(InnerBillAuditUser::getAid, drat.getAid()).eq(InnerBillAuditUser::getCheckstatus, 0));
			if(num <= 0) {
				InnerBillAudit entity = new InnerBillAudit();
				entity.setAid(Long.valueOf(drat.getAid()));
				entity.setAuditstatus(AuditStatusEnum.wait_upload.getValue());
				innerBillAuditService.updateById(entity);
			}

			InnerAccount one = innerAccountService.getOne(new LambdaQueryWrapper<InnerAccount>()
				.eq(InnerAccount::getSid, paramPush.getSid())
			);
			if(one != null){
				one.setAllowPush(2);
				innerAccountService.update(one,new LambdaUpdateWrapper<InnerAccount>().eq(InnerAccount::getSid,paramPush.getSid()));
			}
		}
		return R.status(ret);
	}


	/**
	 * 审核排序
	 * @param list
	 * @return
	 */
	private List<InnerBillAuditUser> sysUser(List<InnerBillAuditUser> list ){
		if(list != null && list.size() > 0){
			for (InnerBillAuditUser financeBillAuditUser : list) {
				UserModel byId = userService.getById(financeBillAuditUser.getUserid());
				financeBillAuditUser.setPriority(byId.getAuditLevel());
			}
			return list;
		}
		return list;
	}


//	@ApiOperation(value = "内部结算-审核人列表查询")
//	@GetMapping("/checkUserList")
//	public List<UserVO> userList(String deptId){
//		//查询前100个用户
//		IPage<User> pageResult = userService.selectUserPage(new Page<User>(1, 100), new User(), Long.parseLong(deptId), null);
//		return UserWrapper.build().listVO(pageResult != null && pageResult.getRecords() != null ? pageResult.getRecords() : new ArrayList<User>());
//	}
	
	@ApiOperation(value = "内部结算-审核人列表查询")
	@ApiOperationSupport(order = 1)
	@GetMapping("/checkUserList")
	public List<UserModel> userList(String deptId){
		return userService.listByDeptId(Long.valueOf(deptId));
	}


	@GetMapping("/page")
	@ApiOperation(value = "分页查询内部结算-推送结算单")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "company", value = "结算方名称", required = false),
		@ApiImplicitParam(name = "queryDate", value = "查询日期(格式：yyyy-MM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "auditStatus", value = "结算单状态", required = false),
		@ApiImplicitParam(name = "checkUserId", value = "审核人员ID", required = false),
		@ApiImplicitParam(name = "checkStatus", value = "审核状态(1-已审核/0-待审核)", required = false)
	})
	public R<IPage<InnerBillAudit>> page(String company, String queryDate, Integer auditStatus, Long checkUserId, Integer checkStatus, Query query){
		QueryWrapper<InnerBillAudit> queryWrapper = Wrappers.<InnerBillAudit>query();
		if(!StringUtils.isEmpty(company)) {
			queryWrapper.eq("ia.COMPANY", company);
		}
		if(!StringUtils.isEmpty(queryDate)) {
			queryWrapper.eq("ia.THEMONTH", queryDate.replace("-", ""));
		}
		if(auditStatus != null) {
			queryWrapper.eq("iba.AUDITSTATUS", auditStatus);
		}
		if(checkUserId != null) {
			queryWrapper.eq("ibau.USERID", checkUserId);
		}
		if(checkStatus != null) {
			queryWrapper.eq("ibau.CHECKSTATUS", checkStatus);
		}
		queryWrapper.orderByDesc("iba.AID");
		Page<InnerBillAudit> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
		//符合条件的aid List
		List<Long> aidList = innerBillAuditService.customAidList(page, queryWrapper);

		IPage<InnerBillAudit> customPage = new Page<InnerBillAudit>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
		if (aidList != null && !aidList.isEmpty()) {
			customPage.setTotal(innerBillAuditService.customCount(queryWrapper));
			List<InnerBillAudit> custom = innerBillAuditService.customList(Wrappers.<InnerBillAudit>query().in("iba.AID", aidList));
			if(custom != null && custom.size() > 0){
				for (InnerBillAudit innerBillAudit : custom) {
					List<InnerDealDetail> list = null;
					list = innerDealDetailService.list(new LambdaQueryWrapper<InnerDealDetail>()
						.eq(InnerDealDetail::getSid,innerBillAudit.getSid())
					);
					if(list != null && list.size() > 0){
						innerBillAudit.setDaelList(list);
					}

					//回传文件列表
					List<InnerBackFile> backFiles = innerBackFileService.list(new LambdaQueryWrapper<InnerBackFile>()
						.eq(InnerBackFile::getAid, innerBillAudit.getAid())
						.eq(InnerBackFile::getIsdelete, 0)
						.orderByDesc(InnerBackFile::getUploadtime)
					);
					if(backFiles != null && backFiles.size() > 0){
						innerBillAudit.setFid(backFiles.get(0).getFid().toString());
						innerBillAudit.setUploadfilename(backFiles.get(0).getUploadfilename());
						innerBillAudit.setUploadfileuri(backFiles.get(0).getUploadfileuri());
						innerBillAudit.setUploadTime(backFiles.get(0).getUploadtime());
					}
				}
			}

			customPage.setRecords(custom);
			if (customPage != null && customPage.getRecords() != null) {
				customPage.getRecords().forEach(f -> {
					StringBuffer userName = new StringBuffer();
					for (InnerBillAuditUser innerBillAuditUser : f.getUserList()) {
						if (innerBillAuditUser.getUserid() == 1394115436887109634L) {
							innerBillAuditUser.setUsername("");
							continue;
						}
						userName.append(innerBillAuditUser.getUsername()).append(",");
					}
					f.setUserNames(userName.deleteCharAt(userName.length() - 1).toString());
				});
			}
		}
		return R.data(customPage);
	}


	/**
	 * 数量查询
	 * @return
	 */
	@GetMapping("/dataCount")
	@ApiOperation(value = "数量查询")
	public R<JSONObject> dateCount(){
		JSONObject result = new JSONObject();
		int uploadCount = innerBillAuditService.count(Wrappers.<InnerBillAudit>lambdaQuery().eq(InnerBillAudit::getAuditstatus, AuditStatusEnum.fin_upload.getValue()));
		int rejectCount = innerBillAuditService.count(Wrappers.<InnerBillAudit>lambdaQuery().eq(InnerBillAudit::getAuditstatus, AuditStatusEnum.fin_reject.getValue()));
		int waitMeCount = innerBillAuditUserService.count(Wrappers.<InnerBillAuditUser>lambdaQuery().eq(InnerBillAuditUser::getUserid, SecureUtil.getUserId()).eq(InnerBillAuditUser::getCheckstatus, 0));
		result.put("uploadCount", uploadCount);
		result.put("rejectCount", rejectCount);
		result.put("waitMeCount", waitMeCount);
		return R.data(result);
	}


	@PostMapping("/reject")
	@ApiOperation(value = "驳回接口")
	public R<String> reject(@RequestParam Long aid, String rejectReason){
		InnerBillAudit entity = new InnerBillAudit();
		entity.setAid(Long.valueOf(aid));
		entity.setRejectreason(rejectReason);
		entity.setAuditstatus(AuditStatusEnum.fin_reject.getValue());
		if(innerBillAuditService.updateById(entity)){
			InnerAccount one = innerAccountService.getOne(new LambdaQueryWrapper<InnerAccount>()
				.eq(InnerAccount::getSid, entity.getSid())
			);
			if(one != null){
				one.setAllowPush(1);
				innerAccountService.update(one,new LambdaUpdateWrapper<InnerAccount>().eq(InnerAccount::getSid,entity.getSid()));
			}
			return R.status(true);
		}
		return R.status(false);
	}


	@PostMapping("/cancel")
	@ApiOperation(value = "作废接口")
	public R<String> cancel(@RequestParam Long aid){
		InnerBillAudit innerBillAudit = innerBillAuditService.getById(aid);
		if(innerBillAudit == null || innerBillAudit.getCreatebyuserid() != SecureUtil.getUserId().longValue()) {
			return R.fail("只有推送者才能作废");
		}
		InnerBillAudit entity = new InnerBillAudit();
		entity.setAid(Long.valueOf(aid));
		entity.setAuditstatus(AuditStatusEnum.fin_cancel.getValue());
		boolean uptRet = innerBillAuditService.updateById(entity);
		if(uptRet) { //作废后，设置全部为审核状态。
			LambdaUpdateWrapper<InnerBillAuditUser> updateWrapper = Wrappers.<InnerBillAuditUser>lambdaUpdate()
				.set(InnerBillAuditUser::getCheckstatus, 1).eq(InnerBillAuditUser::getAid, aid);
			innerBillAuditUserService.update(updateWrapper);
		}

		InnerAccount one = innerAccountService.getOne(new LambdaQueryWrapper<InnerAccount>()
			.eq(InnerAccount::getSid, innerBillAudit.getSid())
		);
		if(one != null){
			one.setAllowPush(1);
			innerAccountService.update(one,new LambdaUpdateWrapper<InnerAccount>().eq(InnerAccount::getSid,innerBillAudit.getSid()));
		}
		return R.status(uptRet);
	}



	@PostMapping("/verify")
	@ApiOperation(value = "审核接口")
	public R<String> verify(@RequestParam Long aid){
		List<InnerBillAuditUser> userList = innerBillAuditUserService.list(Wrappers.<InnerBillAuditUser>lambdaQuery().eq(InnerBillAuditUser::getAid, aid));
		if(!userList.stream().anyMatch(f -> f.getUserid().longValue() == SecureUtil.getUserId())) {
			return R.fail("您没有审核权限");
		}
		if(userList.stream().anyMatch(f -> f.getUserid().longValue() == SecureUtil.getUserId() && f.getCheckstatus() == 1)){
			return R.fail("您已经审核通过");
		}

		List<InnerBillAuditUser> collect = userList.stream()
			.filter(item -> item.getPriority() != 0 && item.getCheckstatus() == 0).collect(Collectors.toList())
			.stream()
			.sorted(Comparator.comparing(InnerBillAuditUser::getPriority)).collect(Collectors.toList());

		log.info("审核人员列表 = {}",collect.toString());
		List<InnerBillAuditUser> filterList = collect.stream().filter(item -> item.getUserid().equals(SecureUtil.getUserId())).collect(Collectors.toList());
		log.info("除该人员外，其他同等级审核人需要去除 = {}",collect.toString());

		collect.removeIf(obj -> !obj.getUserid().equals(SecureUtil.getUserId()) && filterList.get(0).getPriority() == obj.getPriority());
		log.info("过滤后审核人员列表 = {}",collect.toString());

		if(collect.size() > 1){
			for (int i = 0; i < collect.size(); i++) {
				if(collect.get(i).getUserid().equals(SecureUtil.getUserId())){
					log.info("当前审核用户 = {}",collect.get(i).getUserid());
					if(collect.get(i).getPriority() == 1){
						log.info("第一审核人，无需判断");
						break;
					}
					if(i >= 1){
						if(collect.get(i).getPriority() == collect.get(i-1).getPriority()){
							break;
						}else if(collect.get(i).getPriority().longValue() > collect.get(i-1).getPriority().longValue()){
							if(collect.get(i-1).getCheckstatus() == 1){
								break;
							}else {
								return R.fail("上级审核人" + collect.get(i-1).getUsername()+ "还未审核");
							}
						}
					}
				}
			}
		}

		InnerBillAuditUser innerBillAuditUser = userList.stream().filter(f -> f.getUserid().longValue() == SecureUtil.getUserId() && f.getCheckstatus() == 0).findAny().get();
		innerBillAuditUser.setCheckstatus(1);
		innerBillAuditUser.setChecktime(new Date());
		boolean ret = innerBillAuditUserService.updateById(innerBillAuditUser);

		//判断是否所有人都已审核完成
		int count = innerBillAuditUserService.count(Wrappers.<InnerBillAuditUser>lambdaQuery().eq(InnerBillAuditUser::getAid, aid).eq(InnerBillAuditUser::getCheckstatus, 0));
		if(count <= 0) {
			InnerBillAudit entity = new InnerBillAudit();
			entity.setAid(Long.valueOf(aid));
			entity.setAuditstatus(AuditStatusEnum.wait_upload.getValue());
			innerBillAuditService.updateById(entity);
		}
		return R.status(ret);
	}


}
