/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.finance.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.common.base.BaseEntity;
import org.springblade.common.enums.AuditStatusEnum;
import org.springblade.common.enums.OrderStateEnum;
import org.springblade.common.enums.StatusEnum;
import org.springblade.modules.finance.entity.AfterSales;
import org.springblade.modules.finance.entity.OrderGroupon;
import org.springblade.modules.finance.entity.OrderGrouponGoods;
import org.springblade.modules.finance.mapper.OrderGrouponMapper;
import org.springblade.modules.finance.service.*;
import org.springblade.modules.finance.vo.AfterSalesVO;
import org.springblade.modules.finance.vo.OrderGrouponVO;
import org.springblade.modules.groupon.entity.Groupon;
import org.springblade.modules.groupon.entity.UserSelfTake;
import org.springblade.modules.groupon.service.IGrouponService;
import org.springblade.modules.groupon.service.ISelfTakeService;
import org.springblade.modules.groupon.service.IUserSelfTakeService;
import org.springblade.modules.groupon.vo.AppointmentVO;
import org.springblade.modules.groupon.vo.ExportAppointmentVO;
import org.springblade.modules.groupon.vo.ExportPickUpAppointmentVO;
import org.springblade.modules.groupon.vo.GrouponVO;
import org.springblade.modules.groupon.wrapper.GrouponWrapper;
import org.springblade.modules.platform.entity.UserAddress;
import org.springblade.modules.platform.service.IUserAddressService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 团购订单表 服务实现类
 *
 * @author BladeX
 * @since 2023-06-06
 */
@Service
public class OrderGrouponServiceImpl extends ServiceImpl<OrderGrouponMapper, OrderGroupon> implements IOrderGrouponService {

	@Resource
	private IGrouponService grouponService;
	@Resource
	private IUserSelfTakeService userSelfTakeService;
	@Resource
	private IOrderService orderService;
	@Resource
	private IOrderGrouponGoodsService orderGrouponGoodsService;
	@Resource
	private ISelfTakeService selfTakeService;
	@Resource
	private IUserAddressService userAddressService;
	@Lazy
	@Resource
	private IAfterSalesService afterSalesService;
	@Resource
	private IAfterSalesGoodsService afterSalesGoodsService;

	@Override
	public IPage<OrderGrouponVO> selectOrderGrouponPage(IPage<OrderGrouponVO> page, OrderGrouponVO orderGroupon) {
		return page.setRecords(baseMapper.selectOrderGrouponPage(page, orderGroupon));
	}

	@Override
	public IPage<GrouponVO> getCommanderOrder(IPage page, Long userId, Integer grouponState) {
		LambdaQueryWrapper<Groupon> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Groupon::getAuditStatus, AuditStatusEnum.PASS.getValue())
				.eq(Groupon::getStatus, StatusEnum.ENABLE.getValue())
				.eq(Groupon::getOrganizerUserId, userId);
		queryWrapper.orderByDesc(BaseEntity::getCreateTime);
		IPage<Groupon> pages = grouponService.page(page, queryWrapper);
		List<GrouponVO> grouponVOS = GrouponWrapper.build().listVO(pages.getRecords());
		if (CollUtil.isNotEmpty(grouponVOS)) {
			// 查询团长负责的自提点
			UserSelfTake selfTake = userSelfTakeService.lambdaQuery().eq(UserSelfTake::getUserId, userId).one();
			Assert.notNull(selfTake, "团长未绑定自提点");
			// 团购id集合
			List<Long> longs = grouponVOS.stream().map(BaseEntity::getId).collect(Collectors.toList());
			if (!OrderStateEnum.AFTER_SALES.getValue().equals(grouponState)) {
				List<OrderGroupon> list = baseMapper.getGrouponOrder(longs, grouponState);
				if (CollUtil.isNotEmpty(list)) {
					Map<Long, List<OrderGroupon>> map = list.stream().collect(Collectors.groupingBy(OrderGroupon::getGrouponId));
					for (GrouponVO g : grouponVOS) {
						List<OrderGroupon> orderGroupons = map.get(g.getId());
						if (CollUtil.isNotEmpty(orderGroupons)) {
							// 统计全部订单数量和网点数量
							g.setAllOrderNum(orderGroupons.size());
							long count = orderGroupons.stream().filter(e -> e.getSelfTakeId().equals(selfTake.getSelfTakeId())).count();
							g.setDotOrderNum((int) count);
						}
					}
				}
			} else {
				// 查询团购所有的售后数据
				List<AfterSalesVO> afterSalesVOS = afterSalesService.getByGrouponIds(longs);
				Map<Long, List<AfterSalesVO>> map = afterSalesVOS.stream().collect(Collectors.groupingBy(AfterSales::getGrouponId));
				for (GrouponVO g : grouponVOS) {
					List<AfterSalesVO> vos = map.get(g.getId());
					if (CollUtil.isNotEmpty(vos)) {
						// 统计全部订单数量和网点数量
						g.setAllOrderNum(vos.size());
						long count = vos.stream().filter(e -> e.getSelfTakeId().equals(selfTake.getSelfTakeId())).count();
						g.setDotOrderNum((int) count);
					}
				}
			}
		}
		return page.setRecords(grouponVOS);
	}

	@Override
	public IPage<AppointmentVO> getPickUpAppointment(IPage page, Long userId, Integer state, Long salfTakeId) {
		return page.setRecords(baseMapper.selectPickUpAppointment(page, userId, state, salfTakeId));
	}

	@Override
	public List<OrderGroupon> getByGrouponIds(List<Long> grouponIds) {
		return baseMapper.getByGrouponIds(grouponIds);
	}

	@Override
	public List<ExportAppointmentVO> getPickUpAppointmentDataAll(Long grouponId) {
		List<ExportAppointmentVO> list = baseMapper.selectPickUpAppointmentDataAll(grouponId);
		if (CollUtil.isNotEmpty(list)) {
			List<Long> userIds = list.stream().map(ExportAppointmentVO::getUserId).collect(Collectors.toList());
			Map<Long, UserAddress> ua = this.getUserAddress(userIds);
			for (ExportAppointmentVO vo : list) {
				int i = vo.getGoodsNum() - vo.getRefundGoodsNum();
				vo.setSupplyGoodsAmount(vo.getCostPrice().multiply(BigDecimal.valueOf(i)));
				vo.setGrouponAmount(vo.getGrouponPrice().multiply(BigDecimal.valueOf(i)));
				vo.setRefundAmount(vo.getGrouponPrice().multiply(BigDecimal.valueOf(vo.getRefundGoodsNum())));
				vo.setGoodsName(vo.getGoodsName() + "("+vo.getGoodsSpec()+")");
				vo.setOrderStateDesc(OrderStateEnum.getNameByValue(vo.getOrderState()));
				if (CollUtil.isNotEmpty(ua)) {
					UserAddress userAddress = ua.get(vo.getUserId());
					if (userAddress != null) {
						vo.setDeliveryAddress(userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getDetail());
						vo.setConsignee(userAddress.getRealName());
						vo.setConsigneePhone(userAddress.getPhone());
					}
				}
			}
		}
		return list;
	}

	@Override
	public List<ExportPickUpAppointmentVO> getPickUpAppointmentData(Long grouponId) {
		List<ExportPickUpAppointmentVO> vos = baseMapper.selectPickUpAppointmentData(grouponId);
		if (CollUtil.isNotEmpty(vos)) {
			List<Long> userIds = vos.stream().map(ExportPickUpAppointmentVO::getUserId).collect(Collectors.toList());
			Map<Long, UserAddress> ua = this.getUserAddress(userIds);
			List<Long> orderIds = vos.stream().map(ExportPickUpAppointmentVO::getOrderId).collect(Collectors.toList());
			List<OrderGrouponGoods> orderGrouponGoods = orderGrouponGoodsService.lambdaQuery().in(OrderGrouponGoods::getOrderId, orderIds).list();
			Map<Long, List<OrderGrouponGoods>> map = orderGrouponGoods.stream().collect(Collectors.groupingBy(OrderGrouponGoods::getOrderId));
			for (ExportPickUpAppointmentVO vo : vos) {
				List<OrderGrouponGoods> goods = map.get(vo.getOrderId());
				StringBuilder sb = new StringBuilder();
				for (OrderGrouponGoods g : goods) {
					if (g.getGoodsNum() > g.getRefundGoodsNumTotal()) {
						String str = "【"+g.getGoodsNo()+"】" + g.getGoodsName() + "("+g.getGoodsSpec()+")+" + (g.getGoodsNum() - g.getRefundGoodsNumTotal()) + "\n";
						sb.append(str);
					}
				}
				vo.setGoods(sb.toString());
				if (CollUtil.isNotEmpty(ua)) {
					UserAddress userAddress = ua.get(vo.getUserId());
					if (userAddress != null) {
						vo.setDeliveryAddress(userAddress.getProvince() + userAddress.getCity() + userAddress.getDistrict() + userAddress.getDetail());
						vo.setConsignee(userAddress.getRealName());
						vo.setConsigneePhone(userAddress.getPhone());
					}
				}
			}
		}
		return vos;
	}

	private Map<Long, UserAddress> getUserAddress(List<Long> userIds) {
		List<UserAddress> addresses = userAddressService.lambdaQuery().in(UserAddress::getUserId, userIds).eq(UserAddress::getDefaultState, 2).list();
		Map<Long, UserAddress> map = new HashMap<>();
		if (CollUtil.isNotEmpty(addresses)) {
			map = addresses.stream().collect(Collectors.toMap(UserAddress::getUserId, Function.identity()));
		}
		return map;
	}
}
