package com.pj.tb_order;

import java.text.SimpleDateFormat;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.pj.api.client.admin.AdminInterface;
import com.pj.api.client.async_server.AsyncServerInterface;
import com.pj.api.client.level_one_server.LevelOneServerInterface;
import com.pj.api.consts.FeignFactory;
import com.pj.api.dto.*;
import com.pj.common.core.exception.ServiceException;
import com.pj.current.dto.APPLoginUserInfo;
import com.pj.current.satoken.StpAPPUserUtil;
import com.pj.enummj.*;
import com.pj.tb_enterprise.TbEnterprise;
import com.pj.tb_enterprise.TbEnterpriseMapper;
import com.pj.tb_goods_transit.TbGoodsTransit;
import com.pj.tb_goods_transit.TbGoodsTransitMapper;
import com.pj.tb_goods_transit.TbGoodsTransitService;
import com.pj.tb_order.vo.ConfirmVo;
import com.pj.tb_order.vo.OrderVo;
import com.pj.tb_order.vo.PeopleConfirmVo;
import com.pj.tb_order_people_confirm.TbOrderPeopleConfirm;
import com.pj.tb_order_people_confirm.TbOrderPeopleConfirmMapper;
import com.pj.tb_people.TbPeople;
import com.pj.tb_people.TbPeopleMapper;
import com.pj.tb_people.TbPeopleService;
import com.pj.utils.sg.AjaxError;
import com.pj.utils.so.SoMap;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * Service: tb_order -- 订单表
 * @author loovi
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implements IService<TbOrder>{

	/** 底层 Mapper 对象 */
	@Autowired
	TbOrderMapper tbOrderMapper;

	/** 互市组 */
	@Autowired
	private TbPeopleService tbPeopleService;
	@Autowired
	TbOrderPeopleConfirmMapper tbOrderPeopleConfirmMapper;
	@Autowired
	private MethodOrderService methodOrderService;

	@Autowired
	private TbGoodsTransitMapper tbGoodsTransitMapper;
	@Autowired
	private TbGoodsTransitService tbGoodsTransitService;
	@Autowired
	private LevelOneServerInterface levelOneServerInterface;
	@Autowired
	private TbEnterpriseMapper tbEnterpriseMapper;
	@Autowired
	private AsyncServerInterface asyncServerInterface;

	/**
	 * 远程调用
	 */
	@Autowired
	private AdminInterface adminInterface;

	/** 删 */
	void delete(Long id){
		removeById(id);
	}

	/** 改 */
	void update(TbOrder t){
		updateById(t);

	}

	/** 查 */
	TbOrder getById(Long id){
		return super.getById(id);
	}

	/** 查集合 - 根据条件（参数为空时代表忽略指定条件） */
	List<TbOrder> getList(SoMap so) {
		return tbOrderMapper.getList(so);
	}

	/**
	 * 组长或者边民取消订单
	 * @param orderId  一级市场订单ID
	 */
	public boolean cancelOrder(Long orderId){
		//获取登录用户
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
		if(appLoginInfo == null || appLoginInfo.getLoginId() == null)
			throw new RuntimeException("当前登录账号信息已失效!");
		//查询订单
		TbOrder tbOrder = tbOrderMapper.selectById(orderId);
		if(tbOrder == null)throw new ServiceException("订单状态异常!");
		//如果该订单商户已叫车则无法进行取消
		if(tbOrder.getCallCarStatus() == 1 || tbOrder.getCallCarStatus() == 2){
			TbEnterprise enterprise = tbEnterpriseMapper.selectById(appLoginInfo.getFk());
			String phone = null;
			if(enterprise != null)phone = enterprise.getOwnerTel();
			throw new ServiceException("您的订单单号为[ " + tbOrder.getTradeNo() + " ]商户已叫车,无法进行取消,请联系商户电话[ " + phone + " ]进行取消。");
		}
		//将状态设置已取消
		tbOrder.setCancelPeople(1);
		//执行保存
		int updateById = tbOrderMapper.updateById(tbOrder);
		//将goodstransit放开
		if(updateById == 1){
			//获取goods TransitID
			Long goodsId = tbOrder.getGoodsId();
			TbGoodsTransit tbGoodsTransit = tbGoodsTransitMapper.selectById(goodsId);
			if(tbGoodsTransit == null)throw new RuntimeException("商品发布信息异常!");
			//将商品发布修改成可接单状态
			tbGoodsTransit.setIsOrders(0); // 未被下单
			tbGoodsTransit.setEnterpriseConfirm(0); // 修改商户确认状态为未确认
			//执行保存
			int updated = tbGoodsTransitMapper.updateById(tbGoodsTransit);
			//给互助组下属所有人发送取消的message
			PeopleDto peopleDto = levelOneServerInterface.getRpcById(appLoginInfo.getFk());
			methodOrderService.sendGroupMessage(peopleDto.getGroupId(),peopleDto.getBorderName(),false);
			return updated == 1;
		}
		return false;
	}


	/**
	 * 查集合 - 根据条件（参数为空时代表忽略指定条件）
	 * APP专用 与该订单相关的任何人员能看
	 * @param so
	 * @return
	 */
	List<TbOrder> getAPPList(SoMap so) {
		//获取登录用户,登录的用户也许边民,互市组组长,一级市场商家
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();

		//与订单相关的人能看
		List<TbOrder> tbOrderList = methodOrderService.checkType(appLoginInfo.getUserType(),appLoginInfo.getFk(),so);
 		return tbOrderList;
	}

	/** 获取当前登陆人订单集合 */
	public List<TbOrder> selectSelfOrders(SoMap so) {
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
		if(appLoginInfo == null || appLoginInfo.getLoginId() == null)throw new RuntimeException("当前登陆用户信息已失效!");
		so.put("buyUserId",appLoginInfo.getLoginId());
		so.put("deleteStatus", DeleteStatus.DELETE_STATUS_ON.getCode());
		return tbOrderMapper.getList(so);
	}

	/** 查 转售列表：边民组长查看已完结订单，包括已转售/未转售 */
	List<TbOrder> getResaleOrders() {
		//获取app登录用户
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
		if(appLoginInfo == null)throw new RuntimeException("当前登陆用户信息已失效!");

		LambdaQueryWrapper<TbOrder> wrapper = new LambdaQueryWrapper<>();
		//订单状态(0=未完成,1=已完成)
		wrapper.eq(TbOrder::getFinishStatus, 1);
		wrapper.eq(TbOrder::getBuyUserId, appLoginInfo.getLoginId());
		List<TbOrder> tbOrders = tbOrderMapper.selectList(wrapper);

		return tbOrders;
	}

	/** 改 转售状态：根据订单Id把订单改为已转售 */
	boolean updateResaleStatus(Long orderId) {
		LambdaUpdateWrapper<TbOrder> wrapper = new LambdaUpdateWrapper<>();
		wrapper.set(TbOrder::getResaleStatus, 1);
		wrapper.eq(TbOrder::getId, orderId);

		return this.update(wrapper);
	}

	boolean updateEnterpriseConfirm(TbOrder order) {

		// 商户拒绝接单后把商户确认状态改为否，并把商品发布表状态恢复为默认值
		if (2 == order.getEnterpriseConfirm()) {
			LambdaUpdateWrapper<TbGoodsTransit> wrapper = new LambdaUpdateWrapper<>();
			//商品未被下单
			wrapper.set(TbGoodsTransit::getIsOrders, OrderStatus.ORDER_STATUS_ZERO.getCode());
			//商品在售
			wrapper.set(TbGoodsTransit::getGoodsStatus, GoodsStatus.GOODS_STATUS_ON.getCode());

			wrapper.eq(TbGoodsTransit::getId, order.getGoodsId());
			boolean update = tbGoodsTransitService.update(wrapper);

		}

		TbOrder tbOrder=tbOrderMapper.selectById(order.getId());
		//todo:给组长发一条商家消息
		String message = order.getEnterpriseConfirm() == 1 ? "商户已确认,请及时发货。" : "已被商户拒绝,请重新接单或换一家商品。";
		MessageDto dto = new MessageDto();
		dto.setUrl("/pages/market/one/leader/order");
		dto.setUserId(tbOrder.getBuyUserId());
		dto.setContents("你接单的《" + tbOrder.getGoodsNames() + "》" + message);
		adminInterface.messageSave(dto);

		// 修改订单表的商家确认状态
		order.setGoodsId(null);
		boolean flag = updateById(order);

		return flag;
	}

	/**
	 *  查看订单详情
	 * @param orderId  一级市场订单ID
	 * @return 订单的vo
	 */
	public OrderVo orderDetail(Long orderId){
		//查询订单
		TbOrder order = tbOrderMapper.selectById(orderId);
		if(order == null)throw new ServiceException("订单信息异常!");
		//执行封装
		OrderVo orderVo = new OrderVo();
		//数据拷贝
		BeanUtils.copyProperties(order,orderVo);
		return orderVo;
	}

	/**
	 * 根据订单ID查询边民确认订单信息
	 * @param orderId
	 * @return
	 */
	public List<TbOrderPeopleConfirm> selectPeopleConfirmByOrderId(Long orderId){
		List<TbOrderPeopleConfirm> tbOrderPeopleConfirms = tbOrderPeopleConfirmMapper.selectList(new LambdaQueryWrapper<TbOrderPeopleConfirm>().eq(TbOrderPeopleConfirm::getOrderId, orderId));
		if(tbOrderPeopleConfirms.size() > 0){
			tbOrderPeopleConfirms.forEach(item -> {
				item.setOrderId(null);
				item.setGroupId(null);
				item.setId(null);
				item.setPeopleId(null);
			});
		}
		return tbOrderPeopleConfirms;
	}

	public List<PeopleConfirmVo> getPeopleState(SoMap so) {
		List<PeopleConfirmVo> peopleConfirmList = new ArrayList<>();

		// 获取当前订单所有已确认的边民
		List<TbOrderPeopleConfirm> peopleConfirmlist = tbOrderPeopleConfirmMapper.getList(so);
		Set<Long> peopleIds = new HashSet<>();
		for (TbOrderPeopleConfirm tbOrderPeopleConfirm: peopleConfirmlist) {
			peopleIds.add(tbOrderPeopleConfirm.getPeopleId());
		}

		// 获取组内所有边民
		List<TbPeople> peopleList = tbPeopleService.getList(so);
		for (TbPeople people : peopleList) {
			PeopleConfirmVo peopleConfirmVo = new PeopleConfirmVo();
			peopleConfirmVo.setOrderId(so.getLong("orderId"));
			peopleConfirmVo.setGroupId(so.getLong("groupId"));
			peopleConfirmVo.setPeopleId(people.getId());
			peopleConfirmVo.setPeopleName(people.getBorderName());

			// 订单确认状态
			if(peopleIds.contains(people.getId()) || 2 == people.getRole()) {
				peopleConfirmVo.setOrderStatus(1);
			} else {
				peopleConfirmVo.setOrderStatus(0);
			}
			// 进境申报状态
			peopleConfirmVo.setEntryStatus(0);
			// 进口申报状态
			peopleConfirmVo.setImportStatus(0);

			peopleConfirmList.add(peopleConfirmVo);
		}
		return peopleConfirmList;
	}

	/**
	 * 接收订单推送消息，
	 * 边民进行交易确认，
	 * 支付申请，刷脸认
	 * 证，系统发起进行交
	 * 易
	 */
	public void receiveOrderMessageFromHT(){
		//todo: 8月27日 接收航通申报单推送消息
		//1. 获取订单,并将订单保存到订单表

		//2 根据订单内容获取边民集合,创建订单监听表,将该订单内需要完成的边民数逐条保存到监听表内

		//3. 发起支付申请 , 刷脸认证

		//4. 第3步完成且通过后,调用银行的sdk,验证边民的支付信息,由银行将钱转入第三方监管账户,并给出回执

		//5. 拿到银行回执,判断其状态,修改监听表内该订单的完成情况

		//6. 如果监听表内全部边民完成验证,则更新订单表该订单的边民验证完成情况

		//7. todo: 如果订单表的边民验证状态为已完成,将信息同步至航通

	}


	/**
	 * app首页获取边民未确认订单
	 */
	public OrderVo getNoConfirmOrder() {
		//获取登录人
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();

		LambdaQueryWrapper<TbOrder> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TbOrder::getBuyUserId, appLoginInfo.getFk());
		wrapper.eq(TbOrder::getPeopleConfirmStatus, ConfirmStatus.CONFIRM_STATUS_ZERO.getCode());//订单未确认
		wrapper.orderByDesc(TbOrder::getCreateTime);
		wrapper.orderByDesc(TbOrder::getUpdateTime);

		List<TbOrder> tbOrders = tbOrderMapper.selectList(wrapper);
		if(tbOrders.size() > 0) {
			TbOrder order = tbOrders.get(0);

			OrderVo orderVo = new OrderVo();
			BeanUtils.copyProperties(order,orderVo);
			return orderVo;
		}
		return null;
	}

	/**
	 *  获取一级市场边民订单的所有确认状态
	 * @param orderId 一级市场订单表ID
	 */
	public ConfirmVo getConfirmStatus(Long orderId) {
		return tbOrderMapper.getConfirmStatus(orderId);
	}

	/**
	 *  边民订单确认
	 * @param orderId 一级市场订单表ID
	 */
	public boolean confirmOrder(Long orderId){
		TbOrder tbOrder=this.getById(orderId);
		if (tbOrder==null){
			throw new AjaxError("订单不存在");
		}
		// TODO: 2023/8/28 边民发起支付申请，调用银行接口：验证边民支付信息，将货款先存入银行第三方账户，并给出回执
		// 银行返回支付回执为"交易成功"时，方法往下执行

		//获取登录人
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();

		// TODO: 2023/8/29 更新状态保存交易记录
		LambdaUpdateWrapper<TbOrder> wrapper = new LambdaUpdateWrapper<>();
		wrapper.set(TbOrder::getPeopleConfirmStatus, ConfirmStatus.CONFIRM_STATUS_ONE.getCode());//边民确认:1=确认
		wrapper.set(TbOrder::getPeopleConfirmTime, new Date());
		wrapper.set(TbOrder::getUpdateBy, appLoginInfo.getLoginId());
		wrapper.set(TbOrder::getUpdateName, appLoginInfo.getLoginName());
		wrapper.set(TbOrder::getUpdateTime, new Date());
		wrapper.eq(TbOrder::getId, orderId);
		boolean result = update(wrapper);

		// TODO: 2023/8/29 调用航通008接口，发送信息
		sendConfirmMsgToHt(tbOrder);
		return result;
	}

	/**
	 *  边民进口申报确认
	 * @param orderId 一级市场订单表ID
	 */
	public boolean applyOrder(Long orderId){
		TbOrder tbOrder=this.getById(orderId);
		if (tbOrder==null){
			throw new AjaxError("订单不存在");
		}
		//获取登录人
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();

		LambdaUpdateWrapper<TbOrder> wrapper = new LambdaUpdateWrapper<>();
		wrapper.set(TbOrder::getApplyConfirmStatus, ConfirmStatus.CONFIRM_STATUS_ONE.getCode());//进口申报确认:1=确认
		wrapper.set(TbOrder::getApplyConfirmTime, new Date());

		wrapper.set(TbOrder::getUpdateBy, appLoginInfo.getLoginId());
		wrapper.set(TbOrder::getUpdateName, appLoginInfo.getLoginName());
		wrapper.set(TbOrder::getUpdateTime, new Date());

		wrapper.eq(TbOrder::getId, orderId);
		boolean result = update(wrapper);

		// TODO: 2023/8/29 调用航通008接口，发送信息
		sendConfirmMsgToHt(tbOrder);
		return result;
	}

	/**
	 * 发送008信息到航通
	 */
	private void sendConfirmMsgToHt(TbOrder tbOrder){
		TbPeople tbPeople=tbPeopleService.getById(tbOrder.getBuyUserId());
		PeopleConfirmDTO peopleConfirmDTO=new PeopleConfirmDTO();
		peopleConfirmDTO.setBorderName(tbOrder.getBuyUserName());
		peopleConfirmDTO.setIdno(tbPeople.getIdCardNo());
		peopleConfirmDTO.setSettleBillNo(tbOrder.getSettleBillNo());
		peopleConfirmDTO.setPreIeportNo(tbOrder.getPreIeportNo());
		FeignFactory.asyncServerInterface.sendConfirm(peopleConfirmDTO);
	}

	/**
	 *  互助委托申报确认
	 * @param orderId 一级市场订单表ID
	 */
	public boolean cooperOrder(Long orderId){
		//获取登录人
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();

		LambdaUpdateWrapper<TbOrder> wrapper = new LambdaUpdateWrapper<>();
		wrapper.set(TbOrder::getCooperEntrustStatus, ConfirmStatus.CONFIRM_STATUS_ONE.getCode());//互助委托申报确认:1=确认
		wrapper.set(TbOrder::getCooperEntrustTime, new Date());

		wrapper.set(TbOrder::getUpdateBy, appLoginInfo.getLoginId());
		wrapper.set(TbOrder::getUpdateName, appLoginInfo.getLoginName());
		wrapper.set(TbOrder::getUpdateTime, new Date());

		wrapper.eq(TbOrder::getId, orderId);
		boolean result = update(wrapper);

		return result;
	}


	/*-----           正常业务逻辑👆👆    rpc远程调用👇👇 -----*/


	// TODO: 2023/8/28 系统接收到航通接口信息：车辆已出一级市场
	public boolean orderFinish(String billCode){
		//1、todo: 调用银行接口发起划扣：将边民划扣至银行第三方账户的货款，支付至外籍商户的账户
		//收到划扣成功回执后，方法往下制行

		//2、修改一级市场订单支付状态为已支付,修改一级市场订单完成状态为已完成
		//获取登录人
		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
		//获取出了一级市场的所有边民订单
		LambdaQueryWrapper<TbOrder> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(TbOrder::getPreNo, billCode);
		List<TbOrder> tbOrders = tbOrderMapper.selectList(wrapper);

		tbOrders.forEach(order -> {
			order.setTradeStatus(TradeStatus.TRADE_STATUS_ONE.getCode()); //已支付
			order.setTradeTime(new Date()); //支付时间
			order.setPayType(0); //支付类型
			order.setFinishStatus(FinishStatus.FINISH_STATUS_ONE.getCode()); //已完成

			order.setUpdateBy(appLoginInfo.getLoginId());
			order.setUpdateName(appLoginInfo.getLoginName());
			order.setUpdateTime(new Date());

			boolean result = updateById(order);
			//修改失败记录是否应该存表？？
			//if(!result) throw new RuntimeException("当前订单状态修改失败，请联系管理员！");

			if(result) {
				//todo:通知边民转售已经采购的商品；边民上架商品，初步定价
				MessageDto dto = new MessageDto();
				dto.setUrl("/pages/market/one/leader/order");
				dto.setUserId(order.getBuyUserId());
				dto.setContents("你采购的《" + order.getGoodsNames() + "》订单已完成。请及时上架商品到二级市场。");
				adminInterface.messageSave(dto);
			}
		});

		//3、todo: 调用航通接口，发送划扣成功回执信息给航通(只发送),航通暂未提供此接口

		return true;
	}


	/** 远程调用:根据时间和登陆人查询订单 */
	public List<OrderDto> selectOrderList( Long appUserId){
		//判断当前是否已接单
		LambdaQueryWrapper<TbOrder> queryWrapper = new LambdaQueryWrapper<>();
		//根据当天时间查询
//		queryWrapper.eq(TbOrder::getCreateTime,sdf.format(currDay));
		queryWrapper.eq(TbOrder::getCreateBy,appUserId);
		//todo:届时放开该注释
//		queryWrapper.eq(TbOrder::getApply,ApplyStatus.APPLY_STATUS_ONE.getCode()); //申报通过
		queryWrapper.eq(TbOrder::getDeleteStatus,DeleteStatus.DELETE_STATUS_ON.getCode());
		queryWrapper.apply("DATE(create_time) = DATE({0})", new Date()); // 匹配当天的数据
		List<TbOrder> tbOrderList = tbOrderMapper.selectList(queryWrapper);
		//创建返回值集合
		List<OrderDto> result = new ArrayList<>();
		//执行数据封装
		if(tbOrderList.size() == 1){
			tbOrderList.forEach(item -> {
				OrderDto orderDto = new OrderDto();
				BeanUtils.copyProperties(item,orderDto);
				result.add(orderDto);
			});
		}
		//返回
		return result;
	}

	/** 远程调用  查订单 */
	OrderDto getOrderDtoById(Long id){
		TbOrder byId = super.getById(id);
		OrderDto orderDto = new OrderDto();
		BeanUtils.copyProperties(byId,orderDto);
		return orderDto;
	}

	/** 远程调用  修改订单的叫车状态 */
	public boolean updateOrderCallCarStatus(OrderDto orderDto){
		TbOrder tbOrder = new TbOrder();
		BeanUtils.copyProperties(orderDto,tbOrder);
		int update = tbOrderMapper.updateById(tbOrder);
		System.out.println("finish update order call_car_status");
		return update == 1;
	}




}
