package com.seeyon.apps.src_financing.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.util.*;

public class InterestCalculationUtil {

	SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd");


	/**
	 * 还款周期
	 * @return
	 * @throws
	 */
	public List<Date> cycleDates(Calendar startDate,Calendar endDate,int cycleNum,Calendar maxDate) throws ParseException {
		List<Date> cycleDates = new ArrayList<>();
		for(Calendar start = startDate;
			start.getTime().getTime()<maxDate.getTime().getTime();
			start.add(Calendar.MONTH, cycleNum)){
			cycleDates.add(start.getTime());
		}
		cycleDates.add(maxDate.getTime());
		return cycleDates;
	}

	/**
	 * 政府专项利息测算
	 * @return
	 * @throws ParseException
	 */
	public List<Map<String ,Object>> getGovernmentMeasurement(double credit,Date lxstartDate,Date lxendDate,List<String> interestRateList,List<Date> cycleDates ,String contractCode) throws ParseException {
//		设置返回值参数
		List<Map<String,Object>> ret = new ArrayList<>();
//		利率获取
		String[] interestRates = interestRateList.get(0).split("~");
		String interestRatestr = interestRates[1].substring(0,interestRates[1].length()-1);
		double interestRate = stringToNum(interestRatestr);
		for(int i = 0 ; i <cycleDates.size() ; i++){
			Map<String,Object> map = new HashMap<>();
//			设置开始结束时间
			if(i>0){
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(cycleDates.get(i-1));
				calendar.add(Calendar.DAY_OF_MONTH, 1); // 增加1天
				lxstartDate = calendar.getTime();
				lxendDate = cycleDates.get(i);
			}else{

			}
//            计算利息
//			double countInterest = countInterestGovernment(lxstartDate,lxendDate,moneyList,interestRateList,principalList);
			double days = ((lxendDate.getTime()-lxstartDate.getTime())/1000/60/60/24)+1;
			double countInterest = credit*days*interestRate/100/360;
			map.put("计划还款金额",countInterest+"");
//			利息还款编号
			int n = i+1;
			String num= contractCode+n;
			map.put("计划利息还款明细编号",num+"");
//			还款类型枚举固定为利息
			String type = "-4351865301164799504";
			map.put("还款费项类型",type);
//			计划还款日期
			String dateStr = sdf.format(cycleDates.get(i));
			map.put("计划还款日期",dateStr);
			map.put("备注","");
			ret.add(map);
		}


		return ret;
	}

	/**
	 * 农发行利息测算
	 * @return
	 * @throws ParseException
	 */
	public List<Map<String ,Object>> getNFHMeasurement(
			Date lxstartDate,Date lxendDate,List<String> moneyList,List<String> interestRateList, List<String> principalList,List<Date> cycleDates,String contractCode) throws ParseException {
//		设置返回值参数
		List<Map<String,Object>> ret = new ArrayList<>();

		for(int i = 0 ; i <cycleDates.size() ; i++){
			Map<String,Object> map = new HashMap<>();
//			设置开始结束时间
			if(i>0){
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(cycleDates.get(i-1));
				calendar.add(Calendar.DAY_OF_MONTH, 1); // 增加1天
				lxstartDate = calendar.getTime();
				lxendDate = cycleDates.get(i);
			}
//            返回值设置：计划利息还款明细编号，还款费项类型（枚举），计划还款日期，计划还款金额，备注
//            计算利息
			double countInterest = countInterestNFH(lxstartDate,lxendDate,moneyList,interestRateList,principalList);
			map.put("计划还款金额",countInterest+"");
//			利息还款编号
			int n = i+1;
			String num= contractCode+n;
			map.put("计划利息还款明细编号",num+"");
//			还款类型枚举
			String type = "-4351865301164799504";
			map.put("还款费项类型",type);
//			计划还款日期
			String dateStr = sdf.format(cycleDates.get(i));
			map.put("计划还款日期",dateStr);
			map.put("备注","");
			ret.add(map);
		}


		return ret;
	}


	/**
	 * 银行贷款利息测算
	 * @param lxstartDate	利息计算初次开始时间
	 * @param lxendDate		利息计算初次结束时间
	 * @param moneyList		提款信息明细
	 * @param interestRateList	利率信息明细
	 * @param principalList		还款信息明细
	 * @param cycleDates		利息测算时间明细
	 * @return
	 * @throws ParseException
	 */
	public List<Map<String ,Object>> getBankMeasurement(
			Date lxstartDate,Date lxendDate,List<String> moneyList,List<String> interestRateList, List<String> principalList,List<Date> cycleDates,String contractCode) throws ParseException {
		List<Map<String ,Object>> ret = new ArrayList<>();
		for(int i = 0 ; i <cycleDates.size() ; i++){
			Map<String,Object> map = new HashMap<>();
//			设置开始结束时间
			if(i>0){
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(cycleDates.get(i-1));
				calendar.add(Calendar.DAY_OF_MONTH, 1); // 增加1天
				lxstartDate = calendar.getTime();
				lxendDate = cycleDates.get(i);
			}
//            返回值设置：计划利息还款明细编号，还款费项类型（枚举），计划还款日期，计划还款金额，备注
//            计算利息
			System.out.println(sdf.format(lxstartDate)+":"+sdf.format(lxendDate));
			double countInterest = countInterest(lxstartDate,lxendDate,moneyList,interestRateList,principalList);
			map.put("计划还款金额",countInterest+"");
//			利息还款编号
			int n= i+1;
			String num = contractCode+n;
			map.put("计划利息还款明细编号",num+"");
//			还款类型枚举
			String type = "-4351865301164799504";
			map.put("还款费项类型",type);
//			计划还款日期
			String dateStr = sdf.format(cycleDates.get(i));
			map.put("计划还款日期",dateStr);
			map.put("备注","");
			ret.add(map);
		}


		return ret;
	}

	/**
	 * 文本拆分列表
	 * 还本金字段格式：还款费项类型~计划还款时间~计划还款金额~农发行还款规则
	 * 提款字段格式：提款日期~提款金额
	 * 利率还款字段格式：生效日期~利率
	 * @return
	 * @throws ParseException 
	 */
	public String[] stringSplit(String str){
		String[] strs = str.split(";");
		return strs;
	}

	public List<Map<String,Object>> detailedHandle(JSONObject jsonObject,String interestType) throws ParseException {

		//        根据开始时间和合同年限进行时间拆分
		String startDate = jsonObject.getString("startDate");
		Date date = sdf.parse(startDate);
//		开始日期
		Calendar start = Calendar.getInstance();
		start.setTime(date);
		//		结束日期
		Calendar end = Calendar.getInstance();
		end.setTime(date);
		String period = jsonObject.getString("period");
		period = period.substring(0,period.length()-1);
		int periodNum = NumberUtil.convertChineseNumberToArabic(period);
//
//		int periodNum = Integer.parseInt(period)+1;
		end.add(Calendar.YEAR, periodNum);
		end.add(Calendar.DATE, 1);
		//		根据开始结束时间和周期计算时间列表
		String cycle = jsonObject.getString("cycle");
		int cycleNum = getCycleNum(cycle);
		String principal = jsonObject.getString("principal");
		Calendar maxDate = getPrincipalMaxDate(principal);
		List<Date> cycleDates = cycleDates(start,end,cycleNum,maxDate);
		//        获取初次提款时间
		String money = jsonObject.getString("money");
		String[] moneys = money.split(";");
//        转list
		List<String> moneyList = Arrays.asList(moneys);
//        list排序
		Collections.sort(moneyList);
		String[] moenyValue = moneyList.get(0).split("~");
		String moneyDateStr = moenyValue[0];
		//        计算开始时间
		Date lxstartDate = sdf.parse(moneyDateStr);
		//        结算结束时间
		Date lxendDate = cycleDates.get(0);

		//        获取利率初次设置时间
		String interestRate = jsonObject.getString("interestRate");
		String[] interestRates = interestRate.split(";");
		//        转list
		List<String> interestRateList = Arrays.asList(interestRates);
		//        list排序
		Collections.sort(interestRateList);

		//        还本金计划列表
		String[] principals = principal.split(";");
		//        转list
		List<String> principalList = Arrays.asList(principals);
//        list排序
		Collections.sort(principalList);

		String contractDatestr = jsonObject.getString("contractDate");
		Date contractDate = sdf.parse(contractDatestr);
		String creditstr = jsonObject.getString("credit");
		double credit = stringToNum(creditstr);

		List<Map<String,Object>> ret = new ArrayList<>();
		String contractCode = jsonObject.getString("contractCode");
		//		判断利息测算方式
		if("政府专项利息测算".equals(interestType)){
			ret = getGovernmentMeasurement(credit,contractDate,lxendDate,interestRateList,cycleDates,contractCode);
		}else if("农发行利息测算".equals(interestType)){
			ret = getNFHMeasurement(lxstartDate,lxendDate,moneyList,interestRateList,principalList,cycleDates,contractCode);
		}else if("银行贷款利息测算".equals(interestType)){
			ret = getBankMeasurement(lxstartDate,lxendDate,moneyList,interestRateList,principalList,cycleDates,contractCode);
		}
		return ret;
	}


	/**
	 * 银行贷款利息测算
	 * @param startDate	开始时间
	 * @param endDate	结束时间
	 * @param moneyList	提款明细
	 * @param interestRateList	利率明细
	 * @param principalList	还本金明细
	 * @return
	 * @throws ParseException
	 */
	public double countInterest(Date startDate,Date endDate,List<String> moneyList,List<String> interestRateList , List<String> principalList) throws ParseException {

//        设置开始时间的还款金额
		double startNum = 0;
//        开始时间之前所有提款
		for(int i = 0 ; i < moneyList.size() ; i++){
			String[] moneyValues = moneyList.get(i).split("~");
			Date moneyDate = sdf.parse(moneyValues[0]);
			double num = stringToNum(moneyValues[1]);
			if(moneyDate.getTime()<startDate.getTime()){
				startNum+=num;
			}
		}
//        开始时间之前所有还款
		for(int i = 0 ; i < principalList.size() ; i++){
			String[] principalValues = principalList.get(i).split("~");
			Date principalDate = sdf.parse(principalValues[1]);
			double num = stringToNum(principalValues[2]);
			if(principalDate.getTime()<startDate.getTime()){
				startNum-=num;
			}
		}

//        设置开始利率
		double startll = 0;
		for(int i = 0 ; i < interestRateList.size() ; i++){
			String[] interestValues = interestRateList.get(i).split("~");
			Date interestDate = sdf.parse(interestValues[0]);
			double interestValue = stringToNum(interestValues[1].substring(0,interestValues[1].length()-1));
			if(interestDate.getTime()<startDate.getTime()){
				startll = interestValue;
			}
		}

		List<String> strList = new ArrayList();
		strList.add(sdf.format(startDate));
//        添加开始结束日期内的提款信息
		for(int i = 0 ; i < moneyList.size() ; i++){
			String[] moneyValues = moneyList.get(i).split("~");
			Date moneyDate = sdf.parse(moneyValues[0]);
			if(moneyDate.getTime()<endDate.getTime() && moneyDate.getTime()>=startDate.getTime()){
				strList.add(moneyList.get(i));
			}
		}
//        添加开始结束日期内的利率变化信息
		for(int i = 0 ; i < interestRateList.size() ; i++){
			String[] interestValues = interestRateList.get(i).split("~");
			Date interestDate = sdf.parse(interestValues[0]);
			if(interestDate.getTime()<endDate.getTime() && interestDate.getTime()>=startDate.getTime()){
				strList.add(interestRateList.get(i));
			}
		}
//        添加开始结束日期内的计划还本金信息信息
		for(int i = 0 ; i < principalList.size() ; i++){
			String[] principalValues = principalList.get(i).split("~");
			if("本金".equals(principalValues[0])){
				Date principalDate = sdf.parse(principalValues[1]);
				if(principalDate.getTime()<endDate.getTime() && principalDate.getTime()>=startDate.getTime()){
					strList.add(principalList.get(i).substring(3));
				}
			}
		}
		strList.add(sdf.format(endDate));
		Collections.sort(strList);
//        开始金额--》startNum ； 开始利率--》startll；开始时间--》startDate
//        第一个开始时间，最后一个结束时间，中间只存在时间+数字的是提款金额，时间+数字+0的是计划本金还款，时间+数字%的是变化利率
//		System.out.println("开始时间之前金额"+startNum+"开始时间之前利率"+startll+"开始时间"+sdf.format(startDate));
		double lxnum = 0;
		for(int i = 1 ; i <strList.size(); i++ ){
			System.out.println(strList.get(i));
			String[] strs = strList.get(i).split("~");

			switch (strs.length){
				case 1 :
//                    计算出两个时间差
					Date end1 = sdf.parse(strs[0]);
					long days1 = ((end1.getTime()-startDate.getTime())/1000/60/60/24)+1;
					System.out.println("1历史利息"+lxnum+"开始金额"+startNum+"本次计算天数"+days1+"利率"+startll+"本次利息"+startNum*days1*startll/100/360);
					lxnum =lxnum+(startNum*days1*startll/100/360);
					startDate = end1;
					break;
				case 2 :
					boolean endsWithSuffix = strs[1].endsWith("%");
					Date end2 = sdf.parse(strs[0]);
					long days2 = (end2.getTime()-startDate.getTime())/1000/60/60/24;
					System.out.println("2历史利息"+lxnum+"开始金额"+startNum+"本次计算天数"+days2+"利率"+startll+"本次利息"+startNum*days2*startll/100/360);
					lxnum =lxnum+(startNum*days2*startll/100/360);
					if (endsWithSuffix){
						String llstr = strs[1].substring(0,strs[1].length()-1);
						double llnum = stringToNum(llstr);
						startll = llnum;
					} else{
						double num = stringToNum(strs[1]);
						startNum += num;
					}
					startDate = end2;
					break;
				case 3 :
					Date end3 = sdf.parse(strs[0]);
					long days3 = (end3.getTime()-startDate.getTime())/1000/60/60/24;
					System.out.println("3历史利息"+lxnum+"开始金额"+startNum+"本次计算天数"+days3+"利率"+startll+"本次利息"+startNum*days3*startll/100/360);
					lxnum =lxnum+(startNum*days3*startll/100/360);
					double tknum = stringToNum(strs[1]);
					startNum -= tknum;
					startDate = end3;
					break;
			}
		}
		return lxnum;
	}

	/**
	 * 农发行银行贷款利息测算
	 * @param startDate	开始时间
	 * @param endDate	结束时间
	 * @param moneyList	提款明细
	 * @param interestRateList	利率明细
	 * @param principalList	还本金明细
	 * @return
	 * @throws ParseException
	 */
	public double countInterestNFH(Date startDate,Date endDate,List<String> moneyList,List<String> interestRateList , List<String> principalList) throws ParseException {
		List<Double> lixis = new ArrayList<>();
			Date date = startDate;
			double ret = 0 ;
//		根据提款维度进行利息测算
			for(int i = 0 ; i < moneyList.size() ; i++){
				startDate = date;
//			当前提款编号
				int num = i+1;
//			筛选出当前的提款信息和利率信息
//			获取开始时间的提款金额
				String[] moneys = moneyList.get(i).split("~");
				Date moneyDate = sdf.parse(moneys[0]);
				double money = stringToNum(moneys[1]);;
				if(moneyDate.getTime()>=startDate.getTime() && moneyDate.getTime()<endDate.getTime()) {
					startDate = moneyDate;
				}else if(moneyDate.getTime()>endDate.getTime()){
					continue;
				}
				for(int n = 0 ; n < principalList.size(); n++){
							String[] principals = principalList.get(n).split("~");
							Date principalDate = sdf.parse(principals[1]) ;
							if(principalDate.getTime()<startDate.getTime()){
								Map<String,String> nfhDetailed = getNFHDetailed(principals[3]);
								Set<String> keys =nfhDetailed.keySet();
								for(String key:keys){
									if(key.equals(num+"")){
										String moneyStr = nfhDetailed.get(key);
										double principal = stringToNum(moneyStr);
										money = money-principal;
									}
								}
					}
				}
				List<String> strList = new ArrayList();
				strList.add(sdf.format(startDate));
				//        添加开始结束日期内的计划还本金信息
				for(int n = 0 ; n < principalList.size() ; n++){
					String[] principalValues = principalList.get(n).split("~");
					if("本金".equals(principalValues[0])){
						Date principalDate = sdf.parse(principalValues[1]);
						if(principalDate.getTime()<endDate.getTime() && principalDate.getTime()>=startDate.getTime()){
							strList.add(principalList.get(n).substring(3));
						}
					}
				}
				strList.add(sdf.format(endDate));
				Collections.sort(strList);

//			设置利率信息
				String[] interestRates = interestRateList.get(i).split("~");
				double interestRate = Double.parseDouble(interestRates[1].substring(0,interestRates[1].length()-1));
				double lixi = 0;
//				计算利息
				for(int n = 1 ; n <strList.size(); n++ ){
					System.out.println(strList.get(n));
					String[] strs = strList.get(n).split("~");

					switch (strs.length){
						case 1 :
//                    计算出两个时间差
							Date end1 = sdf.parse(strs[0]);
							long days1 = ((end1.getTime()-startDate.getTime())/1000/60/60/24)+1;
							lixi =money*days1*interestRate/100/360;
							startDate = end1;
							lixis.add(lixi);
							break;
						case 3 :
							Date end3 = sdf.parse(strs[0]);
							long days3 = (end3.getTime()-startDate.getTime())/1000/60/60/24;
							lixi =money*days3*interestRate/100/360;
							lixis.add(lixi);
							Map<String,String> nfhDetailed = getNFHDetailed(strs[2]);
							Set<String> keys =nfhDetailed.keySet();
							for(String key:keys){
								if(key.equals(num+"")){
									String moneyStr = nfhDetailed.get(key);
									double principal = stringToNum(moneyStr);
									money = money-principal;
								}
							}
							startDate = end3;
							break;
					}
				}
		}
		for(int i = 0 ; i < lixis.size();i ++){
			ret = ret+ lixis.get(i);
		}
		return ret;
	}

	public Map<String , String> getNFHDetailed(String detailed){
		Map<String,String> ret = new HashMap<>();
		String[] detaileds = detailed.split("_");
		for(String d : detaileds){
			String[] ds = d.split(":");
			ret.put(ds[0],ds[1]);
		}
		return ret;
	}

//	public double countInterestGovernment (){
//		double ret = 0 ;
//		return ret;
//	}

	public double stringToNum(String str){
		double i = 0 ;
		String[] strs = str.split(",");
		StringBuilder numString = new StringBuilder();
		for (String value: strs) {
			numString.append(value);
		}
		i = Double.parseDouble(numString.toString());
		return i;
	}


	public int getCycleNum (String cycle){
		int cycleNum = 1;

		if("月".equals(cycle)){
			cycleNum = 1;
		}else if("季".equals(cycle)){
			cycleNum = 3;
		}else if("半年".equals(cycle)){
			cycleNum = 6;
		}else if("年".equals(cycle)){
			cycleNum = 12;
		}
		return cycleNum;
	}


	/**
	 * 获取本金还款记录中最大还款时间
	 * @param principal
	 * @return
	 */
	public Calendar getPrincipalMaxDate(String principal) throws ParseException {
		Calendar maxDate = Calendar.getInstance();
		String[] principals = principal.split(";");
		Date date = new Date();
		for(int i = 0 ; i < principals.length ; i++){
//			0=类型 ， 1=日期 2=金额 3=农发行规则
			String[] principalss = principals[i].split("~");
			if(i == 0 ){
				date = sdf.parse(principalss[1]);
			}else{
				Date thisDate = sdf.parse(principalss[1]);
				if(thisDate.getTime()>date.getTime()){
					date = thisDate;
				}
			}
		}
		maxDate.setTime(date);
		return maxDate;
	}




}
