package com.sqx.modules.travelconf.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sqx.common.exception.SqxException;
import com.sqx.common.utils.DateUtils;
import com.sqx.map.CommonMapUtils;
import com.sqx.modules.artificer.entity.Artificer;
import com.sqx.modules.artificer.service.ArtificerService;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.enums.CommonEnum;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.common.utils.CommonConfigUtil;
import com.sqx.modules.travelconf.dao.TravelConfDao;
import com.sqx.modules.travelconf.entity.TravelConf;
import com.sqx.modules.travelconf.enums.TravelEnum;
import com.sqx.modules.travelconf.service.TravelConfService;
import com.sqx.modules.travelconf.vo.TravelPriceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * 消息
 */
@Service
public class TravelConfServiceImpl extends ServiceImpl<TravelConfDao, TravelConf> implements TravelConfService {

	@Autowired
	private CommonInfoService commonInfoService;

	@Autowired
	private ArtificerService artificerService;

	@Override
	public TravelConf getConfByAccordingCondition(Integer travelType, Date businessTime) {
		//为空则使用当前系统时间
		if(businessTime == null) businessTime = DateUtil.date();

		//价格类型
		Integer pricingType;
		//往返类型
		Integer fixedType;
		//时令
		Integer seasonsType;
		//时段
		Integer timeIntervalType;

		//从配置文件中取出时间配置(包含很多个)
		Map<Integer,CommonInfo> commonInfoMap = commonInfoService.getMapByCondition(CommonEnum.GroupConditionEnum.V3_TRAVEL_CONF.getValue());

		//价格类型
		CommonInfo pricingTypeConfig = commonInfoMap.get(CommonEnum.V3_TRAVEL_CONF_IS_PRICING.getKey());

		if(pricingTypeConfig == null) {
			//throw new SqxException("无法找到出行配置，请联系管理员！");
			pricingType = TravelEnum.PricingType.TRENDS.getValue();
		}else if(CommonConfigUtil.getBooleanValue(pricingTypeConfig.getValue())){
			pricingType = TravelEnum.PricingType.TRENDS.getValue();
		} else {
			pricingType = TravelEnum.PricingType.FIXED.getValue();
		}

		//往返类型
		CommonInfo fixedTypeConfig = commonInfoMap.get(CommonEnum.V3_TRAVEL_CONF_IS_FIXED.getKey());
		if(pricingTypeConfig == null) {
			fixedType = TravelEnum.FixedType.ONE_WAY.getValue();
		}else if(CommonConfigUtil.getBooleanValue(fixedTypeConfig.getValue())){
			fixedType = TravelEnum.FixedType.RETURN.getValue();
		}else{
			fixedType = TravelEnum.FixedType.ONE_WAY.getValue();
		}

		//夏令时段
		CommonInfo daylightSavingTime = commonInfoMap.get(CommonEnum.V3_TRAVEL_CONF_DAYLIGHT_SAVING_TIME.getKey());
		//冬令时段
		CommonInfo winterTime = commonInfoMap.get(CommonEnum.V3_TRAVEL_CONF_WINTER_TIME.getKey());

		//白天时段
		CommonInfo day = commonInfoMap.get(CommonEnum.V3_TRAVEL_CONF_DAY.getKey());
		//夜间时段
		CommonInfo night = commonInfoMap.get(CommonEnum.V3_TRAVEL_CONF_NIGHT.getKey());

		if(daylightSavingTime == null || winterTime == null || day == null  || night == null){
			throw new SqxException("无法找到时令或白夜时段配置，请联系管理员！");
		}

		String daylightSavingTimeValue = daylightSavingTime.getValue();
		String winterTimeValue = winterTime.getValue();
		String dayValue = day.getValue();
		String nightValue = night.getValue();

		String[] daylightSavingTimeValues = CommonConfigUtil.getArrayValue(daylightSavingTimeValue);
		//为空则自动
		String[] winterTimeValues = CommonConfigUtil.getArrayValue(winterTimeValue);
		String[] dayValues = CommonConfigUtil.getArrayValue(dayValue);
		//为空则自动
		String[] nightValues = CommonConfigUtil.getArrayValue(nightValue);

		if(daylightSavingTimeValues.length != 2 || dayValues.length != 2){
			throw new SqxException("无法找到时令或白夜时段配置，请联系管理员！");
		}

		if(winterTimeValues.length == 0){
			//非夏令时就是冬令时
			boolean isSeasonsType = CommonConfigUtil.calcIsDateSlotCentre(businessTime, daylightSavingTimeValues[0],daylightSavingTimeValues[1]);
			if(isSeasonsType) {
				//夏令时
				seasonsType = TravelEnum.SeasonsType.DAYLIGHT_SAVING_TIME.getValue();
			} else {
				//冬令时
				seasonsType = TravelEnum.SeasonsType.WINTER_TIME.getValue();
			}
		}else{
			//双方混合判断
			boolean isSeasonsType = CommonConfigUtil.calcIsDateSlotCentre(businessTime, daylightSavingTimeValues[0],daylightSavingTimeValues[1]);
			boolean isWinterTimeType = CommonConfigUtil.calcIsDateSlotCentre(businessTime, winterTimeValues[0],winterTimeValues[1]);

			if(isSeasonsType) {
				//夏令时
				seasonsType = TravelEnum.SeasonsType.DAYLIGHT_SAVING_TIME.getValue();
			}else if(isWinterTimeType) {
				//冬令时
				seasonsType = TravelEnum.SeasonsType.WINTER_TIME.getValue();
			} else {
				throw new SqxException("无法找到行配置，请联系管理员！");
			}
		}

		if(nightValues.length == 0){
			//非白天就是夜间
			boolean isTimeIntervalType = CommonConfigUtil.calcIsTimeSlotCentre(businessTime, dayValues[0],dayValues[1]);
			if(isTimeIntervalType) {
				//白天
				timeIntervalType = TravelEnum.TimeIntervalType.DAY.getValue();
			} else {
				//夜间
				timeIntervalType = TravelEnum.TimeIntervalType.NIGHT.getValue();
			}
		}else{
			//双方混合判断
			//前台无法创建 23:00:00-12:00:00的数据，直接甩出错误或者忽略
			throw new SqxException("请清空夜间时间配置，请联系管理员！");
		}
		return getConfByAccordingCondition(pricingType, travelType, seasonsType, timeIntervalType, fixedType);
	}

	public static void main(String[] args) {
		DateTime dateTime = new DateTime("2017-01-05 12:34:23", "yyyy-MM-dd HH:mm:ss");

		DateTime dateTime2 = new DateTime("0105", "MMdd");

		DateTime dateTime3 = new DateTime("123423", "HHmmss");

		String now = DateUtil.today();

		System.out.println(now);

		System.out.println(dateTime);
		System.out.println(dateTime2);
		System.out.println(dateTime3);

		boolean oneRes = CommonConfigUtil.calcIsDateSlotCentre(DateUtil.date(), "0521","0823");
		System.out.println(oneRes);

		boolean oneRes2 = CommonConfigUtil.calcIsTimeSlotCentre(DateUtil.date(), "080000","172200");
		System.out.println(oneRes2);

	}

	@Override
	public TravelConf getConfByAccordingCondition(Integer pricingType, Integer travelType, Integer seasonsType, Integer timeIntervalType, Integer fixedType) {
		if(TravelEnum.PricingType.FIXED.getValue().equals(pricingType)){
			seasonsType = null;
			timeIntervalType = null;
		}
		if(TravelEnum.PricingType.TRENDS.getValue().equals(pricingType)){
			fixedType = null;
		}
		QueryWrapper<TravelConf> qw = new QueryWrapper<>();
		//价格类型
		qw.lambda().eq(pricingType != null, TravelConf::getPricingType, pricingType);
		//出行方式
		qw.lambda().eq(travelType != null, TravelConf::getTravelType, travelType);
		//往返类型
		qw.lambda().eq(fixedType != null, TravelConf::getFixedType, fixedType);
		//时令
		qw.lambda().eq(seasonsType != null, TravelConf::getSeasonsType, seasonsType);
		//时段
		qw.lambda().eq(timeIntervalType != null, TravelConf::getTimeIntervalType, timeIntervalType);
		TravelConf conf = getOne(qw);
		if(conf == null) {
			throw new SqxException("无法找到出行配置，请联系管理员！");
		}
		return conf;
	}

	@Override
	public TravelPriceVo calcTravelPrice(Long artificerId, String toLongitude, String toLatitude, String serveTime) {
		Artificer artificerInfo = artificerService.getById(artificerId);

		Integer cxfs = artificerInfo.getTripWay();//1公交 2出租 3免费
		Integer mfgls = artificerInfo.getTripWayNum();//免费公里数
		if(cxfs==null){
			cxfs = 3;
		}
		if(mfgls==null){
			mfgls = 0;
		}
		Integer travelType = cxfs;//先默认免费

		BigDecimal freeKilometers = new BigDecimal(mfgls);//
		String longitude = artificerInfo.getLongitude();
		String latitude = artificerInfo.getLatitude();
		return calcTravelPrice(travelType, freeKilometers, longitude, latitude, toLongitude, toLatitude,serveTime);
	}
	@Override
	public TravelPriceVo calcTravelPrice(Long artificerId, String toLongitude, String toLatitude, String serveTime, Integer tripWay){
		Artificer artificerInfo = artificerService.getById(artificerId);
		Integer mfgls = artificerInfo.getTripWayNum();//免费公里数
		if(mfgls == null){
			mfgls = 0;
		}
		BigDecimal freeKilometers = new BigDecimal(mfgls);
		String longitude = artificerInfo.getLongitude();
		String latitude = artificerInfo.getLatitude();
		return calcTravelPrice(tripWay, freeKilometers, longitude, latitude, toLongitude, toLatitude,serveTime);
	}

	@Override
	public TravelPriceVo calcTravelPrice(Integer _travelType, BigDecimal freeKilometers, String longitude, String latitude, String toLongitude, String toLatitude, String serveTime){
		TravelPriceVo vo = new TravelPriceVo();
		vo.setFreeKilometers(NumberUtil.decimalFormat("0.00",freeKilometers));

//		Date now = DateTime.now();
		DateUtils.stringToDate(serveTime,"yyyy-MM-dd HH:mm");
		Date now = DateUtils.stringToDate(serveTime,"yyyy-MM-dd HH:mm");;
		//按条件取配置，
		TravelConf conf = getConfByAccordingCondition(_travelType, now);
		vo.setConf(conf);

		Integer pricingType = conf.getPricingType();
		Integer fixedType = conf.getFixedType();
		Integer travelType = conf.getTravelType();
		//Integer seasonsType = conf.getSeasonsType();
		Integer timeIntervalType = conf.getTimeIntervalType();

		//加载距离米数
		//类型转换
		int tripWay = 2;
		if(TravelEnum.TravelType.MASS_TRANSIT.getValue().equals(travelType)) {
			tripWay = 1;
		}
		JSONObject distanceJson = CommonMapUtils.calcTaxiMoneyInfo(tripWay, longitude, latitude, toLongitude, toLatitude);
		if (distanceJson == null) {
			throw new SqxException("驾车路线计算失败!");
		}
		//距离（米）
		Integer distances = distanceJson.getInteger("distance");
		vo.setDistances(distances);

		//转换为公里数【距离（米） * 1000】
		BigDecimal kilometerNum = NumberUtil.div(distances, new BigDecimal("1000"));
		vo.setKilometerNum(NumberUtil.decimalFormat("0.00", kilometerNum));

		BigDecimal usualTravelMoney = BigDecimal.ZERO;
		BigDecimal nightTravelMoney = BigDecimal.ZERO;

		if(TravelEnum.PricingType.FIXED.getValue().equals(pricingType)) {
			//固定的
			//正常出行
			usualTravelMoney = conf.getFixedPrice();
			usualTravelMoney = usualTravelMoney.setScale(2,BigDecimal.ROUND_HALF_UP);
			vo.setUsualTravelMoney(usualTravelMoney);
			//夜间出行
			if(TravelEnum.TimeIntervalType.NIGHT.getValue().equals(timeIntervalType)) {
				//夜间
				nightTravelMoney = conf.getNightTravelExpenses();
			}
			nightTravelMoney = nightTravelMoney.setScale(2,BigDecimal.ROUND_HALF_UP);
			vo.setNightTravelMoney(nightTravelMoney);
			//最终价格
			BigDecimal fixedPrice = usualTravelMoney.add(nightTravelMoney);
			fixedPrice = fixedPrice.setScale(2,BigDecimal.ROUND_HALF_UP);
			vo.setTravelPrice(fixedPrice.toString());
		}else if(TravelEnum.PricingType.TRENDS.getValue().equals(pricingType)){
			//动态的
			if(TravelEnum.TimeIntervalType.NIGHT.getValue().equals(timeIntervalType)) {
				//夜间
				nightTravelMoney = conf.getNightTravelExpenses();
				nightTravelMoney = nightTravelMoney.setScale(2,BigDecimal.ROUND_HALF_UP);
			}
			//起步公里数
			BigDecimal startKilometers = conf.getFreeKilometers();
			//起步价
			BigDecimal startingPrice = conf.getStartingPrice();
			//每公里价格
			BigDecimal pricePerKilometer = conf.getPricePerKilometer();

			//最终价格
			//计算公式为【起步价 + 夜间出行费 + ((公里数 -起步公里数 - 免费公里数) * 每公里价格)= 最终价格】 作废
//			BigDecimal travelPrice = NumberUtil.add(startingPrice, nightTravelExpenses, NumberUtil.mul(NumberUtil.sub(NumberUtil.sub(kilometerNum, ), freeKilometers), pricePerKilometer));
			BigDecimal travelPrice = BigDecimal.ZERO;
			//公里数<免费公里数：车费=夜间出行费
			if(kilometerNum.compareTo(freeKilometers)<0){
				vo.setUsualTravelMoney(BigDecimal.ZERO);
				vo.setNightTravelMoney(nightTravelMoney);
				travelPrice = nightTravelMoney;
				travelPrice = travelPrice.setScale(2,BigDecimal.ROUND_HALF_UP);
				vo.setTravelPrice(travelPrice.toString());
			}else{
				BigDecimal kilometers = kilometerNum.subtract(freeKilometers);
				//公里数>免费公里数：公里数-免费公里数<起步公里数时，车费=夜间出行费+起步价
				if(kilometers.compareTo(startKilometers)<0){
					startingPrice = startingPrice.setScale(2,BigDecimal.ROUND_HALF_UP);
				}else{
					//公里数>免费公里数：公里数-免费公里数>起步公里数时，车费=夜间出行费+起步价+(公里数-免费公里数-起步公里数)*每公里价格
					startingPrice = startingPrice.add(kilometers.subtract(startKilometers).multiply(pricePerKilometer));
					startingPrice = startingPrice.setScale(2,BigDecimal.ROUND_HALF_UP);
				}
				vo.setUsualTravelMoney(startingPrice);
				vo.setNightTravelMoney(nightTravelMoney);
				travelPrice = nightTravelMoney.add(startingPrice);
				travelPrice = travelPrice.setScale(2,BigDecimal.ROUND_HALF_UP);
				vo.setTravelPrice(travelPrice.toString());
			}
		}
		return vo;
	}

}
