package cn.com.countrygarden.bi.main.service.investment.impl;

import cn.com.countrygarden.bi.main.core.Response;
import cn.com.countrygarden.bi.main.core.Result;
import cn.com.countrygarden.bi.main.dao.investment.InvestProjectAccountMapper;
import cn.com.countrygarden.bi.main.dao.investment.InvestProjectInvestmentMapper;
import cn.com.countrygarden.bi.main.dao.investment.InvestRegionInvestmentMapper;
import cn.com.countrygarden.bi.main.dao.investment.InvestRegionTotalMapper;
import cn.com.countrygarden.bi.main.dao.twerp.hm.TbHsprCommunityMapper;
import cn.com.countrygarden.bi.main.dto.ManagerMapOrganTreeDTO;
import cn.com.countrygarden.bi.main.dto.investment.InvestProjectInvestmentVO2;
import cn.com.countrygarden.bi.main.dto.investment.InvestProjectInvestmentVo;
import cn.com.countrygarden.bi.main.exception.ServiceException;
import cn.com.countrygarden.bi.main.model.AccessToken;
import cn.com.countrygarden.bi.main.model.investment.InvestProjectAccount;
import cn.com.countrygarden.bi.main.model.investment.InvestProjectInvestment;
import cn.com.countrygarden.bi.main.model.investment.InvestRegionTotal;
import cn.com.countrygarden.bi.main.model.personnel.PersonnelTag;
import cn.com.countrygarden.bi.main.model.twerp.hm.TbSysOrgan;
import cn.com.countrygarden.bi.main.service.investment.InvestProjectInvestmentService;
import cn.com.countrygarden.bi.main.service.investment.InvestProjectProfitService;
import cn.com.countrygarden.bi.main.service.investment.InvestRegionTotalService;
import cn.com.countrygarden.bi.main.service.twerp.hm.TbSysOrganService;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example.Criteria;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 项目投资-业务逻辑层实现
 *
 * @author 汤婷
 * @email www.justintoforest@gamail.com
 * @url
 * @date 2018-08-15
 */
@Service
@Transactional
public class InvestProjectInvestmentServiceImpl implements InvestProjectInvestmentService {
	@Autowired
	private InvestProjectInvestmentMapper investProjectInvestmentMapper;
	@Resource
	private TbHsprCommunityMapper tbHsprCommunityMapper;
	@Autowired
	private InvestRegionTotalMapper investRegionTotalMapper;

	@Autowired
	private InvestProjectProfitService investProjectProfitService;

	@Autowired
	private TbSysOrganService tbSysOrganService;
	@Autowired
	private InvestProjectAccountMapper investProjectAccountMapper;
	@Autowired
	private InvestRegionTotalService investRegionTotalService;

	private Map<String, String> investRegionTotalId = null;

	public Result queryPageList(String regionId, String projectName, String regionIdStr, AccessToken accessToken) {

		TbSysOrgan tbSysOrgan = tbSysOrganService.findByUserCode(accessToken.getUserCode());
		if (tbSysOrgan == null) {
			tbSysOrgan = new TbSysOrgan();
		}

		if (regionId == null || regionId.equals("") && regionIdStr != null && !regionIdStr.equals("")) {
			regionId = regionIdStr;
		}
		List<InvestProjectInvestment> list = investProjectInvestmentMapper.selectInvestProjectInvestmentAll(regionId,
				projectName, tbSysOrgan.getOrganCode());

		// 获取区域数据
		InvestRegionTotal investments = investRegionTotalMapper.selectByPrimaryKey(Integer.parseInt(regionId));
		// if(investments==null){
		// throw new ServiceException("数据异常,项目关联区域数据不存在！");
		// }
		InvestProjectInvestmentVO2 vo = new InvestProjectInvestmentVO2();
		List<InvestProjectInvestment> newList = new LinkedList<InvestProjectInvestment>();
		Condition condition = null;

		for (InvestProjectInvestment investProjectInvestment : list) {

			condition = new Condition(InvestProjectAccount.class);
			condition.createCriteria().andEqualTo("investProjectInvestmentId", investProjectInvestment.getId());
			int count = investProjectAccountMapper.selectCountByCondition(condition);
			if (count > 0) {

				for (InvestProjectInvestment investProjectInvestment2 : list) {
					if (investProjectInvestment2.getProjectName().equals(investProjectInvestment.getProjectName())) {
						if (investProjectInvestment2.getFlag() == null || investProjectInvestment2.getFlag() != 3) {
							investProjectInvestment2.setFlag(3);
						}

					}
					newList.add(investProjectInvestment2);

				}

			}

		}
		if (newList.size() > 0) {
			Set<InvestProjectInvestment> set = new HashSet<InvestProjectInvestment>(newList);
			list.clear();
			list.addAll(set);

		}
		Collections.sort(list, Comparator.comparing(InvestProjectInvestment::getId).reversed());
		vo.setList(list);
		if (investments != null) {
			vo.setRegionAmountRaised(investments.getRegionAmountRaised().doubleValue());
			vo.setSingleAmountRaised(investments.getSingleAmountRaised().doubleValue());
		}

		return Response.response(vo);
	}

	@Override
	public Result queryById(Integer id) {

		if (id == null) {
			return null;
		}
		InvestProjectInvestment investProjectInvestment = investProjectInvestmentMapper.selectByPrimaryKey(id);
		// 当个人单投已经对项目进行投资时，不能编辑更改区域及项目信息
		Condition condition = null;
		condition = new Condition(InvestProjectAccount.class);
		condition.createCriteria().andEqualTo("investProjectInvestmentId", id);
		int count = investProjectAccountMapper.selectCountByCondition(condition);

		if (count > 0) {
			investProjectInvestment.setFlag(3);
		} else {

			count = investProjectInvestmentMapper
					.findCondInvestProjectInvestment(investProjectInvestment.getProjectName());

			if (count > 0) {
				investProjectInvestment.setFlag(3);
			} else {
				investProjectInvestment.setFlag(1);
			}

		}
		if (investProjectInvestment != null) {
			investRegionTotalId = new HashMap<String, String>();
			// 添加编辑前的区域id，key值固定,汤
			investRegionTotalId.put("investRegionTotalEditPre", investProjectInvestment.getRegionId());
		}

		return Response.response(investProjectInvestment);
	}

	public Result projectNameIsRepeat(InvestProjectInvestment investProjectInvestment, AccessToken accessToken) {
		Condition condition = new Condition(InvestProjectInvestment.class);
		condition.selectProperties("regionId", "projectName");
		Criteria create = condition.createCriteria();
		create.andEqualTo("projectName", investProjectInvestment.getProjectName());
		if (investProjectInvestment.getId() != null && investProjectInvestment.getId() > 0) {
			create.andNotEqualTo("id", investProjectInvestment.getId());
		}
		List<InvestProjectInvestment> investProjectList = investProjectInvestmentMapper.selectByCondition(condition);
		if (investProjectList.size() > 0) {
			if (investProjectList.get(0).getRegionId().equals(investProjectInvestment.getRegionId())) {
				return Response.response("nameExist");
			} else {
				return Response.response("no");
			}
		} else {
			return Response.response("ok");
		}
	}

	public Result add(InvestProjectInvestment investProjectInvestment, AccessToken accessToken) {
		if (accessToken != null) {
			investProjectInvestment.setCreateBy(accessToken.getUserCode());
		}
		investProjectInvestment.setCreateTime(new Date());
		// 项目总跟投金额
		investProjectInvestment.setProjectFollowTotalCapital(investProjectInvestment.getProjectFollowCapital()
				.add(investProjectInvestment.getProjectFollowSingleCapital()));
		// 项目总跟投金额
		if (investProjectInvestment.getProjectFollowTotalCapital().doubleValue() < 0
				|| investProjectInvestment.getProjectFollowCapital().doubleValue() < 0) {
			throw new ServiceException("资金池跟投金额 或 独资金跟投金额 不能为0！请重新填写！");
		}
		Condition condition = null;
		condition = new Condition(InvestProjectInvestment.class);
		condition.createCriteria().andEqualTo("regionId", investProjectInvestment.getRegionId())
				.andEqualTo("projectName", investProjectInvestment.getProjectName());
		List<InvestProjectInvestment> projectInvestments = investProjectInvestmentMapper.selectByCondition(condition);
		if (projectInvestments == null) {
			projectInvestments = new ArrayList<>(1);
		}
		// 当前计算对象混入计算中
		projectInvestments.add(investProjectInvestment);
		// 业务计算
		this.computBusinessData(projectInvestments);
		investProjectInvestmentMapper.deleteByCondition(condition);
		investProjectInvestmentMapper.insertList(projectInvestments);
		// 核对当前区域下所有的项目数据有没有大于区域的数据，如大于添加失败
		addInvestProjectInvestmentDataValidation(investProjectInvestment);
		// 添加项目后个人区域投资重新计算，汤
		investProjectProfitService
				.regionTotalEditComputeRegionInvestment(Integer.parseInt(investProjectInvestment.getRegionId()));
		return Response.response();
	}

	public void addInvestProjectInvestmentDataValidation(InvestProjectInvestment investProjectInvestment) {

		InvestProjectInvestmentVo investProjectInvestmentVo = investProjectInvestmentMapper
				.findInvestProjectInvestmentVoData(investProjectInvestment.getRegionId());

		Condition condition = new Condition(InvestRegionTotal.class);
		condition.selectProperties("regionAmountRaised", "singleAmountRaised");
		condition.createCriteria().andEqualTo("id", investProjectInvestment.getRegionId());
		List<InvestRegionTotal> investRegionTotal = investRegionTotalMapper.selectByCondition(condition);
		if (investRegionTotal.size() < 1) {
			return;
		}

		if (investRegionTotal.get(0).getRegionAmountRaised().doubleValue() < investProjectInvestmentVo
				.getIncomeCapitalTotal().doubleValue()) {
			throw new ServiceException("当前区域下项目收益（资金池）总计已大于区域总募集金额"
					+ investRegionTotal.get(0).getRegionAmountRaised().doubleValue() + "元,操作失败，请更改后再提交");
		}
		if (investRegionTotal.get(0).getSingleAmountRaised().doubleValue() < investProjectInvestmentVo
				.getIncomeCapitalAccountTotal().doubleValue()) {
			throw new ServiceException("当前区域下项目收益（单独资金账户）总计大于区域单独资金总募资金额"
					+ investRegionTotal.get(0).getSingleAmountRaised().doubleValue() + "元,操作失败，请更改后再提交");
		}
		if (investRegionTotal.get(0).getRegionAmountRaised().doubleValue() < investProjectInvestmentVo
				.getIssuedIncomeCapitalTotal().doubleValue()) {
			throw new ServiceException("当前区域下已发放项目收益（资金池）总计已大于区域总募集金额"
					+ investRegionTotal.get(0).getRegionAmountRaised().doubleValue() + "元,操作失败，请更改后再提交");
		}
		if (investRegionTotal.get(0).getSingleAmountRaised().doubleValue() < investProjectInvestmentVo
				.getIssuedIncomeCapitalAccountTotal().doubleValue()) {
			throw new ServiceException("当前区域下已发放项目收益（单独资金账户）总计大于区域单独资金总募资金额"
					+ investRegionTotal.get(0).getSingleAmountRaised().doubleValue() + "元,操作失败，请更改后再提交");
		}

	}

	@Override
	public Result edit(InvestProjectInvestment investProjectInvestment, AccessToken accessToken) {

		investProjectInvestmentMapper.updateByPrimaryKey(investProjectInvestment);
		// 核对当前区域下所有的项目数据有没有大于区域的数据，如大于添加失败
		addInvestProjectInvestmentDataValidation(investProjectInvestment);
		// 重新计算
		Condition condition = new Condition(InvestProjectInvestment.class);
		condition.createCriteria().andEqualTo("regionId", investProjectInvestment.getRegionId())
				.andEqualTo("projectName", investProjectInvestment.getProjectName())
				.andNotEqualTo("id", investProjectInvestment.getId());
		List<InvestProjectInvestment> projectInvestments = investProjectInvestmentMapper.selectByCondition(condition);
		if (projectInvestments == null) {
			projectInvestments = new ArrayList<>(1);
		}
		projectInvestments.add(investProjectInvestment);
		this.computBusinessData(projectInvestments);
		// 添加编辑后的区域id，key值固定，汤

		investRegionTotalId.put("investRegionTotalEditAfter", investProjectInvestment.getRegionId());

		// 2.个人模块重新计算
		investProjectProfitService.projectInvestmentEditComputeProjectProfit(investRegionTotalId);
		return Response.response();
	}

	@Override
	public Result del(Integer id) {
		InvestProjectInvestment projectInvestment = investProjectInvestmentMapper.selectByPrimaryKey(id);
		if (projectInvestment == null) {
			return Response.response();
		}
		String regionId = projectInvestment.getRegionId();
		String projectName = projectInvestment.getProjectName();
		int count = investProjectInvestmentMapper.deleteByPrimaryKey(id);
		// 重新计算
		Condition condition = new Condition(InvestProjectInvestment.class);
		condition.createCriteria().andEqualTo("regionId", regionId).andEqualTo("projectName", projectName);
		List<InvestProjectInvestment> projectInvestments = investProjectInvestmentMapper.selectByCondition(condition);
		if (projectInvestments == null) {
			projectInvestments = new ArrayList<>(1);
		}
		this.computBusinessData(projectInvestments);

		// //区域计算部分重新计算
		// InvestRegionTotal
		// investRegionTotal=investRegionTotalService.findRegionTotalOne(Integer.parseInt(regionId));
		// investRegionTotalService.RegionCompute(investRegionTotal);

		if (count > 0) {
			// 联动删除个人项目收益
			investProjectProfitService.regionTotalEditComputeRegionInvestment(Integer.parseInt(regionId));
		} else {
			throw new ServiceException("InvestProjectInvestmentService接口异常，删除失败");
		}
		return Response.response(count);
	}

	public Result getOrganTreeData() {

		List<InvestRegionTotal> investRegionTotalList = investRegionTotalMapper.selectAll();
		ManagerMapOrganTreeDTO dto = null;
		List<ManagerMapOrganTreeDTO> dtoList = new ArrayList<>();
		for (InvestRegionTotal investRegionTotal : investRegionTotalList) {
			dto = new ManagerMapOrganTreeDTO();
			dto.setCode(String.valueOf(investRegionTotal.getId()));
			dto.setName(investRegionTotal.getRegionName() + "--" + investRegionTotal.getInvestmentName());
			dto.setRegionId(investRegionTotal.getRegionId());

			dtoList.add(dto);
		}

		// List<ManagerMapOrganTreeDTO>
		// dto=investProjectInvestmentMapper.selectAllProjectTree();
		for (ManagerMapOrganTreeDTO organTreeDTO : dtoList) {
			List<ManagerMapOrganTreeDTO> cdto = tbHsprCommunityMapper
					.selectCommunityTreeByOrganCode1(organTreeDTO.getRegionId());
			organTreeDTO.setChildren(cdto);
		}
		return Response.response(dtoList);
	}

	/**
	 * 项目数据计算
	 * 
	 * @param list
	 */
	@Override
	public void computBusinessData(List<InvestProjectInvestment> list) {
		for (InvestProjectInvestment investment : list) {
			investment.setProjectFollowTotalCapital(
					investment.getProjectFollowCapital().add(investment.getProjectFollowSingleCapital()));
		}
		// 项目跟投情况- 计算项目总跟投金额小计
		double heelSmallComput = list.stream().mapToDouble(InvestProjectInvestment::getProjectFollowTotalCapitalDouble)
				.sum();
		// 项目跟投情况-资金池跟投项目金额小计
		double projectFollowCapitalSmallComput = list.stream()
				.mapToDouble(InvestProjectInvestment::getProjectFollowCapitalDouble).sum();
		for (InvestProjectInvestment investment : list) {
			// 项目投资资金收回-阶段性现金返还资金池cash_return_capital
			investment.setCashReturnCapital(new BigDecimal(
					investment.getCashReturnMoney().doubleValue() / heelSmallComput * projectFollowCapitalSmallComput)
							.setScale(2, BigDecimal.ROUND_HALF_UP));

			// 项目投资资金收回-阶段性现金返还独资金 减法
			investment.setCashReturnCapitalAccount(investment.getCashReturnMoney()
					.subtract(investment.getCashReturnCapital()).setScale(2, BigDecimal.ROUND_HALF_UP));
			// 项目投资资金收回 -本金返还
			investment.setPrincipalReturnCapital(new BigDecimal(investment.getPrincipalReturnMoney().doubleValue()
					/ heelSmallComput * projectFollowCapitalSmallComput).setScale(2, BigDecimal.ROUND_HALF_UP));
			// 项目投资资金收回 -单独资金账户
			investment.setPrincipalReturnCapitalAccount(investment.getPrincipalReturnMoney()
					.subtract(investment.getPrincipalReturnCapital()).setScale(2, BigDecimal.ROUND_HALF_UP));
			// 本金未收回-资金池
			investment.setPrincipalNotrecoveredCapital(investment.getProjectFollowCapital()
					.subtract(investment.getPrincipalReturnCapital()).setScale(2, BigDecimal.ROUND_HALF_UP));
			// 本金未收回-单独资金账户
			investment.setPrincipalNotrecoveredCapitalAccount(investment.getProjectFollowSingleCapital()
					.subtract(investment.getPrincipalReturnCapitalAccount()).setScale(2, BigDecimal.ROUND_HALF_UP));

			investProjectInvestmentMapper.updateByPrimaryKeySelective(investment);
		}

	}

	// 项目筛选条件下拉框数据
	public Result queryRegionsList() {

		Condition condition = new Condition(InvestRegionTotal.class);
		condition.selectProperties("id", "investmentName", "flag");
		return Response.response(investRegionTotalMapper.selectByCondition(condition));
	}

	// 项目筛选条件下拉框数据
	public Result findProjectAll(String regionId) {

		return Response.response(investProjectInvestmentMapper.findProjectElSelectData(regionId));

	}

	@Override
	public Result getProjectInfo(String regionId) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("regionId", regionId);
		List<InvestProjectInvestment> list = investProjectInvestmentMapper.findInvestProjectInvestment(map);
		return Response.response(list);
	}

}