package com.roncoo.education.course.service.api.auth.biz;

import com.github.abel533.echarts.Option;
import com.github.abel533.echarts.axis.CategoryAxis;
import com.github.abel533.echarts.axis.ValueAxis;
import com.github.abel533.echarts.code.AxisType;
import com.github.abel533.echarts.code.Magic;
import com.github.abel533.echarts.code.Tool;
import com.github.abel533.echarts.code.Trigger;
import com.github.abel533.echarts.feature.MagicType;
import com.github.abel533.echarts.series.Line;
import com.roncoo.education.course.common.bo.OrderInfoCloseBO;
import com.roncoo.education.course.common.bo.auth.*;
import com.roncoo.education.course.common.dto.auth.*;
import com.roncoo.education.course.service.dao.CourseDao;
import com.roncoo.education.course.service.dao.OrderInfoDao;
import com.roncoo.education.course.service.dao.OrderPayDao;
import com.roncoo.education.course.service.dao.impl.mapper.entity.Course;
import com.roncoo.education.course.service.dao.impl.mapper.entity.OrderInfo;
import com.roncoo.education.course.service.dao.impl.mapper.entity.OrderInfoExample;
import com.roncoo.education.course.service.dao.impl.mapper.entity.OrderInfoExample.Criteria;
import com.roncoo.education.course.service.dao.impl.mapper.entity.OrderPay;
import com.roncoo.education.system.feign.vo.SysVO;
import com.roncoo.education.system.feign.interfaces.IFeignSys;
import com.roncoo.education.user.feign.vo.LecturerVO;
import com.roncoo.education.user.feign.vo.UserExtVO;
import com.roncoo.education.user.feign.interfaces.IFeignLecturer;
import com.roncoo.education.user.feign.interfaces.IFeignUserExt;
import com.roncoo.education.util.base.*;
import com.roncoo.education.util.config.SystemUtil;
import com.roncoo.education.util.enums.*;
import com.roncoo.education.util.pay.PayUtil;
import com.roncoo.education.util.tools.BeanUtil;
import com.roncoo.education.util.tools.DateUtil;
import com.roncoo.education.util.tools.NOUtil;
import com.xiaoleilu.hutool.util.ObjectUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 订单信息表
 *
 * @author wujing
 */
@Component
public class AuthApiOrderInfoBiz extends BaseBiz {

	@Autowired
	private OrderInfoDao orderInfoDao;
	@Autowired
	private OrderPayDao orderPayDao;
	@Autowired
	private CourseDao courseDao;

	@Autowired
	private IFeignSys bossSys;
	@Autowired
	private IFeignUserExt bossUserExt;
	@Autowired
	private IFeignLecturer bossLecturer;

	/**
	 * 订单列表接口
	 *
	 * @param authOrderInfoListBO
	 * @return
	 */
	public Result<Page<AuthOrderInfoListDTO>> listForPage(AuthOrderInfoListBO authOrderInfoListBO) {
		OrderInfoExample Example = new OrderInfoExample();
		Criteria c = Example.createCriteria();
		c.andUserNoEqualTo(authOrderInfoListBO.getUserNo());
		c.andIsShowUserEqualTo(IsShowEnum.YES.getCode());
		// 初始化页数
		if (StringUtils.isEmpty(authOrderInfoListBO.getPageCurrent())) {
			authOrderInfoListBO.setPageCurrent(1);
		}
		if (StringUtils.isEmpty(authOrderInfoListBO.getPageSize())) {
			authOrderInfoListBO.setPageSize(20);
		}
		// 0用于判断前端,查出除了关闭状态的所有订单
		if (authOrderInfoListBO.getOrderStatus() != null && !authOrderInfoListBO.getOrderStatus().equals(Integer.valueOf(0))) {
			c.andOrderStatusEqualTo(authOrderInfoListBO.getOrderStatus());
		} else {
			c.andOrderStatusNotEqualTo(OrderStatusEnum.CLOSE.getCode());
		}
		Example.setOrderByClause(" id desc ");
		Page<OrderInfo> page = orderInfoDao.listForPage(authOrderInfoListBO.getPageCurrent(), authOrderInfoListBO.getPageSize(), Example);
		Page<AuthOrderInfoListDTO> dtopage = PageUtil.transform(page, AuthOrderInfoListDTO.class);
		for (AuthOrderInfoListDTO dto : dtopage.getList()) {
			Course course = courseDao.getById(dto.getCourseId());
			dto.setCourseLogo(course.getCourseLogo());
			dto.setCourseId(course.getId());
		}
		return Result.success(dtopage);
	}

	/**
	 * 订单下单接口
	 *
	 * @param authOrderPayBO
	 * @return
	 */
	@Transactional
	public Result<AuthOrderPayDTO> pay(AuthOrderPayBO authOrderPayBO) {
		// 参数校验
		verifyParam(authOrderPayBO);

		// 课程信息
		Course course = courseDao.getByCourseIdAndStatusId(authOrderPayBO.getCourseId(), StatusIdEnum.YES.getCode());
		if (StringUtils.isEmpty(course)) {
			return Result.error("courseId不正确");
		}

		// 根据用户编号查找用户信息
		UserExtVO userextVO = bossUserExt.getByUserNo(authOrderPayBO.getUserNo());
		if (ObjectUtil.isNull(userextVO) || StatusIdEnum.NO.getCode().equals(userextVO.getStatusId())) {
			return Result.error("userNo不正确");
		}

		// 获取讲师信息
		LecturerVO lecturerVO = bossLecturer.getByLecturerUserNo(course.getLecturerUserNo());
		if (StringUtils.isEmpty(lecturerVO) || !StatusIdEnum.YES.getCode().equals(lecturerVO.getStatusId())) {
			return Result.error("lecturerUserNo不正确");
		}

		// 判断所要购买的课程是否已经购买------(如果课程为测试支付课程，可以重复下单，不提示已经购买，去掉后面一截判断即可正常使用)
		if (!checkOrderInfo(authOrderPayBO.getUserNo(), authOrderPayBO.getCourseId()) && !SystemUtil.TEST_COURSE.equals(course.getId().toString())) {
			return Result.error("已经购买该课程，请勿重复购买");
		}

		// 创建订单信息
		OrderInfo orderInfo = createOrderInfo(authOrderPayBO, course, userextVO, lecturerVO);

		// 创建支付订单
		OrderPay orderPay = createOrderPay(orderInfo);

		// 查找系统配置信息
		SysVO sys = bossSys.getSys();
		if (ObjectUtil.isNull(sys)) {
			return Result.error("找不到系统配置信息");
		}
		if (StringUtils.isEmpty(sys.getPayKey()) || StringUtils.isEmpty(sys.getPaySecret()) || StringUtils.isEmpty(sys.getPayUrl())) {
			return Result.error("payKey,paySecret或payUrl未配置");
		}

		// 调用支付接口
		String payMessage = PayUtil.roncooPay(String.valueOf(orderPay.getSerialNumber()), orderInfo.getCourseName(), orderInfo.getPricePaid(), orderInfo.getPayType(), sys.getPayKey(), sys.getPaySecret(), sys.getPayUrl(), sys.getNotifyUrl());
		if (StringUtils.isEmpty(payMessage)) {
			return Result.error("系统繁忙，请稍后再试");
		}

		// 返回实体
		AuthOrderPayDTO dto = new AuthOrderPayDTO();
		dto.setPayMessage(payMessage);
		dto.setOrderNo(String.valueOf(orderInfo.getOrderNo()));
		dto.setCourseName(orderInfo.getCourseName());
		dto.setPayType(orderInfo.getPayType());
		dto.setPrice(orderInfo.getPricePaid());
		return Result.success(dto);
	}

	/**
	 * 订单继续支付接口
	 *
	 * @param orderInfoContinuePayBO
	 * @return
	 */
	@Transactional
	public Result<AuthOrderPayDTO> continuePay(AuthOrderInfoContinuePayBO authOrderInfoContinuePayBO) {
		if (StringUtils.isEmpty(authOrderInfoContinuePayBO.getOrderNo())) {
			return Result.error("orderNo不能为空");
		}
		if (StringUtils.isEmpty(authOrderInfoContinuePayBO.getPayType())) {
			return Result.error("payType不能为空");
		}

		// 订单校验
		OrderInfo orderInfo = orderInfoDao.getByOrderNo(authOrderInfoContinuePayBO.getOrderNo());
		if (ObjectUtil.isNull(orderInfo)) {
			return Result.error("orderNo不正确，没有找到订单信息");
		}
		if (!checkOrderInfo(orderInfo.getUserNo(), orderInfo.getCourseId())) {
			return Result.error("已经购买该课程，请勿重复购买");
		}

		OrderPay orderPay = orderPayDao.getByOrderNo(orderInfo.getOrderNo());
		if (ObjectUtil.isNull(orderPay)) {
			return Result.error("orderNo不正确，没有找到流水号");
		}

		// 查找课程信息
		Course course = courseDao.getByCourseIdAndStatusId(orderInfo.getCourseId(), StatusIdEnum.YES.getCode());
		if (StringUtils.isEmpty(course) || !StatusIdEnum.YES.getCode().equals(course.getStatusId())) {
			return Result.error("根据订单的课程编号没找到对应的课程信息!");
		}
		// 根据用户编号查找用户信息
		UserExtVO userExtVO = bossUserExt.getByUserNo(orderInfo.getUserNo());
		if (StringUtils.isEmpty(userExtVO) || !StatusIdEnum.YES.getCode().equals(userExtVO.getStatusId())) {
			return Result.error("根据传入的userNo没找到对应的用户信息!");
		}

		// 更新订单信息
		orderInfo.setPayType(authOrderInfoContinuePayBO.getPayType());
		orderInfo.setOrderStatus(OrderStatusEnum.WAIT.getCode());
		orderInfoDao.updateById(orderInfo);

		// 重新生成新的支付流水
		orderPay.setOrderStatus(OrderStatusEnum.WAIT.getCode());
		orderPay.setSerialNumber(NOUtil.getSerialNumber());
		orderPayDao.updateById(orderPay);

		// 查找系统配置信息
		SysVO sys = bossSys.getSys();
		if (ObjectUtil.isNull(sys)) {
			return Result.error("找不到系统配置信息");
		}
		if (StringUtils.isEmpty(sys.getPayKey()) || StringUtils.isEmpty(sys.getPaySecret()) || StringUtils.isEmpty(sys.getPayUrl())) {
			return Result.error("payKey,paySecret或payUrl未配置");
		}

		// 调用支付接口
		String payMessage = PayUtil.roncooPay(String.valueOf(orderPay.getSerialNumber()), orderInfo.getCourseName(), orderInfo.getPricePaid(), orderInfo.getPayType(), sys.getPayKey(), sys.getPaySecret(), sys.getPayUrl(), sys.getNotifyUrl());
		if (StringUtils.isEmpty(payMessage)) {
			return Result.error("系统繁忙，请稍后再试");
		}

		// 返回实体
		AuthOrderPayDTO dto = new AuthOrderPayDTO();
		dto.setPayMessage(payMessage);
		dto.setOrderNo(String.valueOf(orderInfo.getOrderNo()));
		dto.setCourseName(orderInfo.getCourseName());
		dto.setPayType(orderInfo.getPayType());
		dto.setPrice(orderInfo.getPricePaid());
		return Result.success(dto);
	}

	/**
	 * 关闭订单信息接口
	 *
	 * @param continuePay
	 * @return
	 */
	@Transactional
	public Result<String> close(OrderInfoCloseBO orderInfoCloseBO) {
		if (StringUtils.isEmpty(orderInfoCloseBO.getOrderNo())) {
			return Result.error("orderNo不能为空");
		}
		OrderInfo orderInfo = orderInfoDao.getByOrderNo(orderInfoCloseBO.getOrderNo());
		if (ObjectUtil.isNull(orderInfo)) {
			return Result.error("orderNo不正确,找不到订单信息");
		}
		OrderPay orderPay = orderPayDao.getByOrderNo(orderInfo.getOrderNo());
		if (ObjectUtil.isNull(orderPay)) {
			return Result.error("orderNo不正确,找不到流水号");
		}
		if (!OrderStatusEnum.WAIT.getCode().equals(orderInfo.getOrderStatus())) {
			return Result.error("该订单已经处理完成，不需要再处理");
		}
		// 根据用户编号查找用户信息
		UserExtVO userExtVO = bossUserExt.getByUserNo(orderInfo.getUserNo());
		if (StringUtils.isEmpty(userExtVO) || !StatusIdEnum.YES.getCode().equals(userExtVO.getStatusId())) {
			return Result.error("根据传入的userNo没找到对应的用户信息!");
		}
		orderInfo.setOrderStatus(OrderStatusEnum.CLOSE.getCode());
		int orderNum = orderInfoDao.updateById(orderInfo);
		if (orderNum < 1) {
			throw new BaseException("订单信息更新失败");
		}
		orderPay.setOrderStatus(OrderStatusEnum.CLOSE.getCode());
		int orderPayNum = orderPayDao.updateById(orderPay);
		if (orderPayNum < 1) {
			throw new BaseException("订单流水号更新失败");
		}
		return Result.success("订单关闭成功");
	}

	/**
	 * 订单详情
	 *
	 * @param orderInfoBO
	 * @return
	 */
	public Result<AuthOrderInfoDTO> view(AuthOrderInfoViewBO authOrderInfoViewBO) {
		if (StringUtils.isEmpty(authOrderInfoViewBO.getOrderNo())) {
			return Result.error("orderNo不能为空");
		}
		// 根据订单编号查找订单信息
		OrderInfo order = orderInfoDao.getByOrderNo(authOrderInfoViewBO.getOrderNo());
		if (ObjectUtil.isNull(order)) {
			return Result.error("orderNo不正确");
		}
		return Result.success(BeanUtil.copyProperties(order, AuthOrderInfoDTO.class));
	}

	/**
	 * 查找订单信息列表信息
	 *
	 * @param authOrderInfoListBO
	 * @return
	 */
	public Result<Page<AuthOrderInfoListForLecturerDTO>> list(AuthOrderInfoListBO authOrderInfoListBO) {
		if (StringUtils.isEmpty(authOrderInfoListBO.getLecturerUserNo())) {
			return Result.error("lecturerUserNo不正确");
		}
		OrderInfoExample example = new OrderInfoExample();
		Criteria c = example.createCriteria();
		c.andLecturerUserNoEqualTo(authOrderInfoListBO.getLecturerUserNo());
		c.andIsShowUserEqualTo(IsShowUserEnum.YES.getCode());
		c.andPricePaidGreaterThanOrEqualTo(BigDecimal.valueOf(0.5));
		// 不查找已经关闭了的订单
		c.andOrderStatusEqualTo(OrderStatusEnum.SUCCESS.getCode());
		example.setOrderByClause(" id desc ");
		Page<OrderInfo> page = orderInfoDao.listForPage(authOrderInfoListBO.getPageCurrent(), authOrderInfoListBO.getPageSize(), example);
		Page<AuthOrderInfoListForLecturerDTO> dtoPage = PageUtil.transform(page, AuthOrderInfoListForLecturerDTO.class);
		for (AuthOrderInfoListForLecturerDTO dto : dtoPage.getList()) {
			dto.setPhone(dto.getMobile().substring(0, 3) + "****" + dto.getMobile().substring(7, dto.getMobile().length()));
		}
		return Result.success(dtoPage);
	}

	/**
	 * 讲师收益折线图
	 *
	 * @param authOrderInfoForChartsBO
	 * @return
	 */
	public Result<Option> charts(AuthOrderInfoForChartsBO authOrderInfoForChartsBO) {
		Option option = new Option();
		option.legend().data("订单收益", "日期时间");
		option.tooltip().trigger(Trigger.axis).axisPointer();
		option.calculable(true);
		// 设置x轴数据
		CategoryAxis categoryAxis = new CategoryAxis();
		List<String> xData = new ArrayList<>();
		payTime(authOrderInfoForChartsBO, xData);
		for (String x : xData) {
			categoryAxis.data(x);
		}
		option.xAxis(categoryAxis);

		// 设置y轴数据
		ValueAxis valueAxis = new ValueAxis();
		valueAxis.type(AxisType.value);
		valueAxis.splitArea().show(true);
		valueAxis.axisLabel().formatter("{value}元");
		option.yAxis(valueAxis);
		// 第一条线为当天收益
		Line line1 = new Line();
		List<AuthOrderInfoLecturerIncomeDTO> dtoList = sumByLecturerUserNoAndData(authOrderInfoForChartsBO.getLecturerUserNo(), xData);
		for (AuthOrderInfoLecturerIncomeDTO dto : dtoList) {
			for (BigDecimal bi : dto.getLecturerProfit()) {
				line1.data(bi);
			}
		}
		line1.name("讲师	");
		option.series(line1);
		option.toolbox().show(true).feature(new MagicType(Magic.line, Magic.bar), Tool.restore, Tool.saveAsImage);
		return Result.success(option);
	}

	private List<AuthOrderInfoLecturerIncomeDTO> sumByLecturerUserNoAndData(Long lecturerUserNo, List<String> xData) {
		List<AuthOrderInfoLecturerIncomeDTO> list = new ArrayList<>();
		AuthOrderInfoLecturerIncomeDTO dto = new AuthOrderInfoLecturerIncomeDTO();
		List<BigDecimal> countPaidPrice = new ArrayList<>();
		for (String date : xData) {
			BigDecimal sum = orderInfoDao.sumLecturerUserNoAndData(lecturerUserNo, date);
			countPaidPrice.add(sum);
		}
		dto.setLecturerProfit(countPaidPrice);
		list.add(dto);
		return list;
	}

	private List<String> payTime(AuthOrderInfoForChartsBO authOrderInfoForChartsBO, List<String> xData) {
		// 如果时间为空，则传入现在当前时间七天前的订单
		if (authOrderInfoForChartsBO.getBeginCreate() == null && authOrderInfoForChartsBO.getEndCreate() == null) {
			authOrderInfoForChartsBO.setBeginCreate(DateUtil.format(DateUtil.addDate(new Date(), -7)));
			authOrderInfoForChartsBO.setEndCreate(DateUtil.format(new Date()));
		}
		Calendar tempStart = Calendar.getInstance();
		tempStart.setTime(DateUtil.parseDate(authOrderInfoForChartsBO.getBeginCreate(), "yyyy-MM-dd"));
		tempStart.add(Calendar.DAY_OF_YEAR, 0);
		Calendar tempEnd = Calendar.getInstance();
		tempEnd.setTime(DateUtil.parseDate(authOrderInfoForChartsBO.getEndCreate(), "yyyy-MM-dd"));
		tempEnd.add(Calendar.DAY_OF_YEAR, 1);
		while (tempStart.before(tempEnd)) {
			xData.add(DateUtil.formatDate(tempStart.getTime()));
			tempStart.add(Calendar.DAY_OF_YEAR, 1);
		}
		return xData;
	}

	/**
	 * 校验下单时传入的参数
	 *
	 * @param orderInfoPayBO
	 */
	private void verifyParam(AuthOrderPayBO authOrderPayBO) {
		if (StringUtils.isEmpty(authOrderPayBO.getUserNo())) {
			throw new BaseException("userNo不能为空");
		}
		if (StringUtils.isEmpty(authOrderPayBO.getCourseId())) {
			throw new BaseException("courseId不能为空");
		}
		if (StringUtils.isEmpty(authOrderPayBO.getPayType())) {
			throw new BaseException("payType不能为空");
		}
		if (StringUtils.isEmpty(authOrderPayBO.getChannelType())) {
			throw new BaseException("channelType不能为空");
		}
	}

	/**
	 * 判断课程是否已经支付
	 */
	private boolean checkOrderInfo(long userNo, long courseId) {
		OrderInfo orderInfo = orderInfoDao.getByUserNoAndCourseId(userNo, courseId);
		if (ObjectUtil.isNull(orderInfo)) {
			return true;
		} else if (!OrderStatusEnum.SUCCESS.getCode().equals(orderInfo.getOrderStatus())) {
			return true;
		}
		return false;
	}

	/**
	 * 创建订单支付信息
	 */
	private OrderPay createOrderPay(OrderInfo retrunOrderInfo) {
		OrderPay orderpay = new OrderPay();
		orderpay.setOrderNo(retrunOrderInfo.getOrderNo());
		orderpay.setOrderStatus(retrunOrderInfo.getOrderStatus());
		orderpay.setPayType(retrunOrderInfo.getPayType());
		orderpay.setSerialNumber(NOUtil.getSerialNumber());
		orderPayDao.save(orderpay);
		return orderpay;
	}

	/**
	 * 创建订单信息表
	 */
	private OrderInfo createOrderInfo(AuthOrderPayBO authOrderPayBO, Course course, UserExtVO userextvo, LecturerVO lecturervo) {
		OrderInfo orderInfo = new OrderInfo();
		orderInfo.setCourseName(course.getCourseName());
		orderInfo.setCourseId(course.getId());
		orderInfo.setPricePaid(course.getCourseDiscount());
		orderInfo.setPricePayable(course.getCourseOriginal());
		orderInfo.setLecturerUserNo(lecturervo.getLecturerUserNo());
		orderInfo.setLecturerName(lecturervo.getLecturerName());
		orderInfo.setUserNo(userextvo.getUserNo());
		orderInfo.setMobile(userextvo.getMobile());
		orderInfo.setRegisterTime(userextvo.getGmtCreate());
		orderInfo.setOrderNo(NOUtil.getOrderNo()); // 订单号，不要使用IdWorker生成
		orderInfo.setCourseId(course.getId());
		orderInfo.setCourseName(course.getCourseName());
		orderInfo.setPriceDiscount(BigDecimal.ZERO);
		orderInfo.setPlatformProfit(BigDecimal.ZERO);
		orderInfo.setLecturerProfit(BigDecimal.ZERO);
		orderInfo.setIsShowUser(IsShowUserEnum.YES.getCode());
		orderInfo.setTradeType(TradeTypeEnum.ONLINE.getCode());
		orderInfo.setPayType(authOrderPayBO.getPayType());
		orderInfo.setChannelType(authOrderPayBO.getChannelType());
		orderInfo.setRemarkCus(authOrderPayBO.getRemarkCus());
		orderInfo.setOrderStatus(OrderStatusEnum.WAIT.getCode());
		orderInfoDao.save(orderInfo);
		return orderInfo;
	}

	class updateCount implements Runnable {
		private Course course;

		public updateCount(Course course) {
			this.course = course;
		}

		@Override
		public void run() {
			Course info = new Course();
			info.setCountBuy(course.getCountBuy() + 1);
			info.setId(course.getId());
			courseDao.updateById(course);
		}
	}

}
