/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.delivery.comment.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yami.shop.bean.app.dto.ProductItemDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.dto.TzTransportDto;
import com.yami.shop.bean.enums.TransportChargeType;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.Json;
import com.yami.shop.delivery.comment.model.Transfee;
import com.yami.shop.delivery.comment.model.TransfeeFree;
import com.yami.shop.delivery.comment.model.Transport;
import com.yami.shop.bean.model.Transport2;
import com.yami.shop.delivery.comment.service.Transport2Service;
import com.yami.shop.delivery.comment.service.TransportManagerService;
import com.yami.shop.delivery.comment.service.TransportService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.ShopDetailService;
import com.yami.shop.service.SkuService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class TransportManagerServiceImpl implements TransportManagerService {

    @Autowired
    private ProductService productService;
    @Autowired
    private SkuService skuService;
    @Autowired
    private TransportService transportService;
    @Autowired
    private Transport2Service transport2Service;

    @Autowired
    private ShopDetailService shopDetailService;

    @Override
    public Double calculateTransfee(ProductItemDto productItem, UserAddr userAddr) {

        // 获取商品
        Product product = productService.getProductByProdId(productItem.getProdId());
        // 用户所在区域的id
        Long areaId = userAddr.getAreaId();
        // 物流模板
        Product.DeliveryModeVO deliveryModeVO = Json.parseObject(product.getDeliveryMode(), Product.DeliveryModeVO.class);
        if (product.getShopId() == 0L) {
            //0为平台包邮
            return 0.0;
        }
        // 没有店铺配送的方式
        if (!deliveryModeVO.getHasShopDelivery()) {
            return 0.0;
        }
        if (product.getDeliveryTemplateId() == null) {
            return 0.0;
        }

        //找出该产品的运费项  运费模板
        Transport transport = transportService.getTransportAndAllItems(product.getDeliveryTemplateId());
        //商家把运费模板删除
        if (transport == null) {
            return 0.0;
        }

        Sku sku = skuService.getSkuBySkuId(productItem.getSkuId());

        // 用于计算运费的件数
        Double piece = 0.0;

        if (Objects.equals(TransportChargeType.COUNT.value(), transport.getChargeType())) {
            // 按件数计算运费
            piece = Double.valueOf(productItem.getProdCount());
        } else if (Objects.equals(TransportChargeType.WEIGHT.value(), transport.getChargeType())) {
            // 按重量计算运费
            double weight = sku.getWeight() == null ? 0 : sku.getWeight();
            piece = Arith.mul(weight, productItem.getProdCount());
        } else if (Objects.equals(TransportChargeType.VOLUME.value(), transport.getChargeType())) {
            // 按体积计算运费
            double volume = sku.getVolume() == null ? 0 : sku.getVolume();
            piece = Arith.mul(volume, productItem.getProdCount());
        }

        //如果有包邮的条件
        if (transport.getHasFreeCondition() == 1) {
            // 获取所有的包邮条件
            List<TransfeeFree> transfeeFrees = transport.getTransfeeFrees();
            for (TransfeeFree transfeeFree : transfeeFrees) {
                List<Area> freeCityList = transfeeFree.getFreeCityList();
                for (Area freeCity : freeCityList) {
                    if (!Objects.equals(freeCity.getAreaId(), areaId)) {
                        continue;
                    }
                    //包邮方式 （0 满x件/重量/体积包邮 1满金额包邮 2满x件/重量/体积且满金额包邮）
                    if ((transfeeFree.getFreeType() == 0 && piece >= transfeeFree.getPiece()) ||
                            (transfeeFree.getFreeType() == 1 && productItem.getProductTotalAmount() >= transfeeFree.getAmount()) ||
                            (transfeeFree.getFreeType() == 2 && piece >= transfeeFree.getPiece() && productItem.getProductTotalAmount() >= transfeeFree.getAmount())) {
                        return 0.0;
                    }
                }
            }
        }

        //订单的运费项
//        Transfee transfee = null;
//        List<Transfee> transfees = transport.getTransfees();
//
//        for (Transfee dbTransfee : transfees) {
//            // 将该商品的运费设置为默认运费
//            if (transfee == null && CollectionUtil.isEmpty(dbTransfee.getCityList())) {
//                transfee = dbTransfee;
//            }
//            // 如果在运费模板中的城市找到该商品的运费，则将该商品由默认运费设置为该城市的运费
//            boolean isContainer = dbTransfee.getCityList().stream().anyMatch(area -> area.getAreaId().equals(areaId));
//            if(isContainer){
//                transfee = dbTransfee;
//                break;
//            }
//            // 如果在运费模板中的城市找到该商品的运费，则退出整个循环
//            if (transfee != null && CollectionUtil.isNotEmpty(transfee.getCityList())) {
//                break;
//            }
//        }
//
//        // 如果无法获取到任何运费相关信息，则返回0运费
//        if (transfee == null) {
//            return 0.0;
//        }
//
//        // 产品的运费
//        Double fee = transfee.getFirstFee();
//        // 如果件数大于首件数量，则开始计算超出的运费
//        if (piece > transfee.getFirstPiece()) {
//            // 续件数量
//            Double prodContinuousPiece = Arith.sub(piece, transfee.getFirstPiece());
//            // 续件数量的倍数，向上取整
//            Integer mulNumber = (int) Math.ceil(Arith.div(prodContinuousPiece, transfee.getContinuousPiece()));
//            // 续件数量运费
//            Double continuousFee = Arith.mul(mulNumber, transfee.getContinuousFee());
//            fee = Arith.add(fee, continuousFee);
//        }
        return getTransfee(areaId, transport, piece);
    }

    @Override
    public Double calculateTransfeeSecond(List<ShopCartItemDto> productItems, UserAddr userAddr) {


        // 重新计算运费 ,理论上立即购买和购物车结算时，都能计算运费
        // 同一个订单，同一个商店,运费模板相同，做整合
        // 同一个运费模板，有的订单，没有店铺配送方式，运费为0.0

        // 商品的总运费
        // 店铺的
        double totalTransfee = 0.0;

        // 1 去除没有店铺配送的订单和运费模板的订单
        List<ShopCartItemDto> notTransPortList = removeNotTransPort(productItems, userAddr);
        if (CollectionUtils.isEmpty(notTransPortList)) {
            return 0.0;
        }
        // 2 去掉重复运费模板后的订单
        List<ShopCartItemDto> shopCartItemDtos = removeRepeatList(notTransPortList, userAddr);
        if (CollectionUtils.isEmpty(shopCartItemDtos)) {
            return 0.0;
        }
        // 3 将 shopCartItemDtos的每一项 和 notTransPortList 的每一项进行比较
        //   将重复的数据筛选处理，如果筛选出来的集合大小 大于 1 ，表示有重复的集合；
        //   如果 等于 1 表示无重复的集合；无为空情况（为空也不影响计算)
        for (ShopCartItemDto shopCartItemDto : shopCartItemDtos) {
            // 某个运费模板相同的订单集合
            List<ShopCartItemDto> repeatList = getRepeatList(notTransPortList, shopCartItemDto);
            // 根据 repeatList 计算出运费
            Double transfee = repeatListTransfee(repeatList, userAddr);
            totalTransfee = Arith.add(totalTransfee, transfee);
        }
        return totalTransfee;
    }

    @Override
    public Double calculateTransfeeSecond2(Long shopId, UserAddr userAddr) {
        Double longitude = userAddr.getLongitude();
        Double latitude = userAddr.getLatitude();
        if (longitude.equals(0.0)) {
            throw new GlobalException("收货地址经纬度为空");
        }

        ShopDetail shopDetailByShopId = shopDetailService.getShopDetailByShopId(shopId);
        double v = calculateDistance(latitude, longitude, Double.valueOf(shopDetailByShopId.getShopLat()), Double.valueOf(shopDetailByShopId.getShopLng()));
        Transport2 byDistance = transport2Service.findByDistance(shopId, v);
        if (ObjectUtil.isEmpty(byDistance)) {
            System.out.println("超出配送范围");
            return -1.0;
        }
        // todo 计算价格

        return byDistance.getPiece();
    }

    @Override
    public TzTransportDto calculateTransfeeSecondTransport2(Long shopId, UserAddr userAddr, Long channelId) {
        Double longitude = userAddr.getLongitude();
        Double latitude = userAddr.getLatitude();
        System.out.println("用户经度"+latitude);
        System.out.println("用户纬度"+longitude);
        System.out.println("用户信息"+userAddr);
        if (longitude.equals(0.0)) {
            throw new GlobalException("收货地址经纬度为空");
        }

        ShopDetail shopDetailByShopId = shopDetailService.getShopDetailByShopId(shopId);
        System.out.println("门店经度"+shopDetailByShopId.getShopLat());
        System.out.println("门店纬度"+shopDetailByShopId.getShopLng());
        double v = calculateDistance(latitude, longitude,
                Double.parseDouble(shopDetailByShopId.getShopLat()), Double.parseDouble(shopDetailByShopId.getShopLng()));
        //Transport2 byDistance = transport2Service.findByDistance(shopId, platform);
        Transport2 byDistance = transport2Service.findByPlatform(channelId);
        System.out.println("byDistance"+byDistance);

        TzTransportDto tzTransportDto = new TzTransportDto();
        BeanUtils.copyProperties(byDistance, tzTransportDto);
        tzTransportDto.setTargetDistance(v);
        return tzTransportDto;
    }

    @Override
    public Double calculateTransfeeSecond2(Long shopId, UserAddr userAddr, Double weight) {
        Double longitude = userAddr.getLongitude();
        Double latitude = userAddr.getLatitude();
        if (longitude.equals(0.0)) {
            throw new GlobalException("收货地址经纬度为空");
        }

        ShopDetail shopDetailByShopId = shopDetailService.getShopDetailByShopId(shopId);
        double v = calculateDistance(latitude, longitude, Double.valueOf(shopDetailByShopId.getShopLat()), Double.valueOf(shopDetailByShopId.getShopLng()));
        Transport2 byDistance = transport2Service.findByDistance(shopId, v, weight);
        if (ObjectUtil.isEmpty(byDistance)) {
            System.out.println("超出配送范围或重量超重");
            return -1.0;
        }
        // todo 计算价格

        return byDistance.getPiece();
    }

    @Override
    public Transport2 calculateTransfeeStart(Long shopId, Double longitude, Double latitude) {
        if (longitude.equals(0.0)) {
            throw new GlobalException("收货地址经纬度为空");
        }
        ShopDetail shopDetailByShopId = shopDetailService.getShopDetailByShopId(shopId);
        if (ObjectUtils.isNotEmpty(shopDetailByShopId)) {
            double v = calculateDistance(latitude, longitude, Double.valueOf(shopDetailByShopId.getShopLat()), Double.valueOf(shopDetailByShopId.getShopLng()));
            Transport2 byDistance = transport2Service.findByDistance(shopId, v);
            if (ObjectUtil.isEmpty(byDistance)) {
                throw new GlobalException("超出配送范围");
            }
            // todo 计算价格

            return byDistance;
        }
        return null;
    }


    // 1 先去掉重复运费模板的订单
    // 2 筛选出运费模板相同的订单
    // 3 计算出运费模板相同的订单的运费
    // 4 计算运费模板

    /**
     * 去除没有店铺后的订单
     *
     * @param productItems 原用户所有的未处理订单
     * @param userAddr
     * @return 去除没有店铺后的订单
     */
    private List<ShopCartItemDto> removeNotTransPort(List<ShopCartItemDto> productItems, UserAddr userAddr) {
        // 保存去掉没有运费模板重复的订单
        List<ShopCartItemDto> resList = new ArrayList<>();

        for (ShopCartItemDto productItem : productItems) {
            // 获取商品
            Product product = productService.getProductByProdId(productItem.getProdId());
            // 物流模板
            Product.DeliveryModeVO deliveryModeVO = Json.parseObject(product.getDeliveryMode(), Product.DeliveryModeVO.class);
            // 没有店铺配送的方式
            if (!deliveryModeVO.getHasShopDelivery()) {
                continue;
            }
            if (product.getDeliveryTemplateId() == null) {
                continue;
            }
            //找出该产品的运费项  运费模板
            Transport transport = transportService.getTransportAndAllItems(product.getDeliveryTemplateId());
            //商家把运费模板删除
            if (transport == null) {
                continue;
            }
            resList.add(productItem);
        }
        return resList;
    }

    /**
     * 为了方便筛选统计，先去掉运费模板重复的订单,不计算没有店铺配送的订单
     *
     * @param productItems 用户下单的订单列表或者订单
     * @param userAddr
     * @return 去掉运费模板重复的订单
     */
    private List<ShopCartItemDto> removeRepeatList(List<ShopCartItemDto> productItems, UserAddr userAddr) {
        // 保存去掉运费模板重复的订单
        List<ShopCartItemDto> resList = new ArrayList<>();
        // 保存transportId
        List<Long> repeatList = new ArrayList<>();
        for (ShopCartItemDto productItem : productItems) {
            // 获取商品
            Product product = productService.getProductByProdId(productItem.getProdId());
            //找出该产品的运费项  运费模板
            Transport transport = transportService.getTransportAndAllItems(product.getDeliveryTemplateId());
            if (repeatList.contains(transport.getTransportId())) {
                continue;
            } else {
                repeatList.add(transport.getTransportId());
                // 把运费模板不同的订单保存起来
                resList.add(productItem);
            }
        }
        return resList;
    }


    /**
     * 将运费模板重复的订单筛选处理
     *
     * @param productItems 原用户所有的未处理订单
     * @param productItem  去重后的订单的某一项订单
     * @return 去掉运费模板重复后的订单
     */
    private List<ShopCartItemDto> getRepeatList(List<ShopCartItemDto> productItems, ShopCartItemDto productItem) {
        // 在productItems集合中筛选出，productItem 的运费模板相同的订单
        // 保存运费模板相同的订单
        List<ShopCartItemDto> resList = new ArrayList<>();
        // 此部分是查询出 productItem 的运费模板

        // 获取商品
        Product productOne = productService.getProductByProdId(productItem.getProdId());
        //找出该产品的运费项  运费模板
        Transport transportOne = transportService.getTransportAndAllItems(productOne.getDeliveryTemplateId());

        for (ShopCartItemDto item : productItems) {
            // 获取商品
            Product product = productService.getProductByProdId(item.getProdId());
            //找出该产品的运费项  运费模板
            Transport transport = transportService.getTransportAndAllItems(product.getDeliveryTemplateId());
            if (Objects.equals(transportOne.getTransportId(), transport.getTransportId())) {
                // 如果有相同的运费模板,保存起来
                resList.add(item);
            }
        }
        return resList;
    }


    /**
     * 计算出运费模板重复的订单运费
     *
     * @param productItems 运费模板是重复的订单
     * @param userAddr
     * @return
     */
    private Double repeatListTransfee(List<ShopCartItemDto> productItems, UserAddr userAddr) {

        // 重复订单的运费
        double transportfee = 0.0;
        if (CollectionUtils.isEmpty(productItems)) {
            return 0.0;
        }
//        if (productItems.size()==1){
//            // 如果集合只有一个商品
//            ShopCartItemDto shopCartItemDto = productItems.get(0);
//            Double transfee = calculateTransfee(shopCartItemDto, userAddr);
//            return transfee;
//        }
        if (productItems.size() >= 1) {
            // 获取第一个订单，将订单的重量体积和件数求和，加给第一个订单
            ShopCartItemDto shopCartItemDto = productItems.get(0);
            Product productFirst = productService.getProductByProdId(productItems.get(0).getProdId());

            Sku skuOne = skuService.getSkuBySkuId(productItems.get(0).getSkuId());
            // 商品的件数 (总的件数)
            Integer prodCount = productItems.get(0).getProdCount();
            // 商品的重量
            double weight = skuOne.getWeight() == null ? 0 : skuOne.getWeight();
            // 总的重量
            double pieceWeight = Arith.mul(weight, prodCount);
            // 商品的体积
            double volume = skuOne.getVolume() == null ? 0 : skuOne.getVolume();
            // 总的体积
            double pieceVolume = Arith.mul(volume, productItems.get(0).getProdCount());

            // 商品总金额
            Double productTotalAmount = productItems.get(0).getProductTotalAmount();

            for (int i = 1; i < productItems.size(); i++) {
                // 商品的件数
                Integer prodCountI = productItems.get(i).getProdCount();
                prodCount += prodCountI;
                // 获取商品
                Product product = productService.getProductByProdId(productItems.get(i).getProdId());
                Sku sku = skuService.getSkuBySkuId(productItems.get(i).getSkuId());
                // 商品的重量
                double weightSku = sku.getWeight() == null ? 0 : sku.getWeight();
                pieceWeight = Arith.add(pieceWeight, Arith.mul(weightSku, prodCountI));

                // 商品的体积
                double volumeSku = skuOne.getVolume() == null ? 0 : skuOne.getVolume();
                pieceVolume = Arith.add(pieceVolume, Arith.mul(volumeSku, prodCountI));
                // 商品总金额
                productTotalAmount = Arith.add(productTotalAmount, productItems.get(i).getProductTotalAmount() == null ? 0.0 : productItems.get(i).getProductTotalAmount());

            }


            // 用户所在区域的id
            Long areaId = userAddr.getAreaId();

            //找出该产品的运费项  运费模板
            Transport transport = transportService.getTransportAndAllItems(productFirst.getDeliveryTemplateId());
            //商家把运费模板删除
            if (transport == null) {
                return 0.0;
            }

            // 用于计算运费的件数
            double piece = 0.0;

            if (Objects.equals(TransportChargeType.COUNT.value(), transport.getChargeType())) {
                // 按件数计算运费
                piece = Double.valueOf(prodCount);
            } else if (Objects.equals(TransportChargeType.WEIGHT.value(), transport.getChargeType())) {
                // 按重量计算运费
                piece = Double.valueOf(pieceWeight);
            } else if (Objects.equals(TransportChargeType.VOLUME.value(), transport.getChargeType())) {
                // 按体积计算运费
                piece = Double.valueOf(pieceVolume);
            }
            //如果有包邮的条件
            if (transport.getHasFreeCondition() == 1) {
                // 获取所有的包邮条件
                List<TransfeeFree> transfeeFrees = transport.getTransfeeFrees();
                for (TransfeeFree transfeeFree : transfeeFrees) {
                    List<Area> freeCityList = transfeeFree.getFreeCityList();
                    for (Area freeCity : freeCityList) {
                        if (!Objects.equals(freeCity.getAreaId(), areaId)) {
                            continue;
                        }
                        //包邮方式 （0 满x件/重量/体积包邮 1满金额包邮 2满x件/重量/体积且满金额包邮）
                        if ((transfeeFree.getFreeType() == 0 && piece >= transfeeFree.getPiece()) ||
                                (transfeeFree.getFreeType() == 1 && productTotalAmount >= transfeeFree.getAmount()) ||
                                (transfeeFree.getFreeType() == 2 && piece >= transfeeFree.getPiece() && productTotalAmount >= transfeeFree.getAmount())) {
                            return 0.0;
                        }
                    }
                }
            }

            //订单的运费项
            return getTransfee(areaId, transport, piece);
        }

        return 0.0;
    }

    private Double getTransfee(Long areaId, Transport transport, double piece) {
        Transfee transfee = null;
        List<Transfee> transfees = transport.getTransfees();
        for (Transfee dbTransfee : transfees) {
            // 将该商品的运费设置为默认运费
            if (transfee == null && CollectionUtil.isEmpty(dbTransfee.getCityList())) {
                transfee = dbTransfee;
            }
            // 如果在运费模板中的城市找到该商品的运费，则将该商品由默认运费设置为该城市的运费
            boolean isContainer = dbTransfee.getCityList().stream().anyMatch(area -> area.getAreaId().equals(areaId));
            if (isContainer) {
                transfee = dbTransfee;
                break;
            }
            // 如果在运费模板中的城市找到该商品的运费，则退出整个循环
            if (transfee != null && CollectionUtil.isNotEmpty(transfee.getCityList())) {
                break;
            }
        }

        // 如果无法获取到任何运费相关信息，则返回0运费
        if (transfee == null) {
            return 0.0;
        }
        // 产品的运费
        Double fee = transfee.getFirstFee();
        // 如果件数大于首件数量，则开始计算超出的运费
        if (piece > transfee.getFirstPiece()) {
            // 续件数量
            Double prodContinuousPiece = Arith.sub(piece, transfee.getFirstPiece());
            // 续件数量的倍数，向上取整
            Integer mulNumber = (int) Math.ceil(Arith.div(prodContinuousPiece, transfee.getContinuousPiece()));
            // 续件数量运费
            Double continuousFee = Arith.mul(mulNumber, transfee.getContinuousFee());
            fee = Arith.add(fee, continuousFee);
        }

        return fee == null ? 0.0 : fee;
    }

    private static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final double R = 6371; // 地球半径，单位：公里
        // 转为弧度
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        // Haversine公式
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);

        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c; // 距离单位：公里
    }

    public static void main(String[] args) {
        calculateDistance(26.65581, 106.62511, 26.609417, 106.644542);
    }
}
