package com.hfkj.channel.gas.shell;

import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hfkj.entity.BsAgentMer;
import com.hfkj.entity.BsGasOilGunNo;
import com.hfkj.entity.BsGasOilPrice;
import com.hfkj.entity.BsMerchant;
import com.hfkj.service.agent.BsAgentMerService;
import com.hfkj.service.gas.BsGasOilGunNoService;
import com.hfkj.service.gas.BsGasOilPriceService;
import com.hfkj.service.gas.BsGasService;
import com.hfkj.service.merchant.BsMerchantService;
import com.hfkj.sysenum.merchant.MerchantSourceTypeEnum;
import com.hfkj.sysenum.merchant.MerchantStatusEnum;
import com.hfkj.sysenum.gas.GasOilPriceStatusEnum;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 重庆壳牌油站服务
 * @className: CqShellPetroleumService
 * @author: HuRui
 * @date: 2024/7/22
 **/
@Component
public class CqShellPetroleumGasService {

    @Resource
    private BsMerchantService merchantService;
    @Resource
    private BsGasService gasService;
    @Resource
    private BsGasOilPriceService gasOilPriceService;
    @Resource
    private BsGasOilGunNoService gasOilGunNoService;
    @Resource
    private BsAgentMerService agentMerService;
    /**
     * 刷取全量油站
     * @throws Exception
     */
    public void refresh() throws Exception {
        // 最新全量加油站数据
        List<Object> gasDataList = new ArrayList<>();
        // 初始化页数
        Integer totalPageNum = 3;
        // 每页数量
        Integer pageSize = 50;
        for (int pageIndex = 1; pageIndex <= totalPageNum;pageIndex++) {
            // 查询油站
            JSONObject object = CqShellPetroleumRequestService.gasPageQueryAllStation(pageIndex, pageSize);
            // 总页数
            JSONObject pageInfo = JSONObject.parseObject(object.getString("pageInfo"));
            totalPageNum = (pageInfo.getInteger("totalCount") + pageSize - 1) / pageSize;
            // 加入全量数据集合
            gasDataList.addAll(JSONArray.parseArray(object.getString("infoList")));
        }
        // 设备核心数目
        int processorsNum = Runtime.getRuntime().availableProcessors();

        Long startTime = System.currentTimeMillis();
        System.out.println("本次更新任务开始");
        System.out.println("重庆壳牌");
        // 初始化线程池
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                processorsNum * 2,
                processorsNum * 2,
                4,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue(processorsNum * 2 * 10),
                new ThreadPoolExecutor.DiscardPolicy());

        // 大集合拆分成N个小集合，然后用多线程去处理数据，确保不会因为数据量过大导致执行过慢
        List<List<Object>> splitNList = splitList(gasDataList, 10);
        // 记录单个任务的执行次数
        CountDownLatch countDownLatch = new CountDownLatch(splitNList.size());
        // 对拆分的集合进行批量处理, 先拆分的集合, 再多线程执行
        for (List<Object> singleList : splitNList) {
            // 线程池执行
            threadPool.execute(new Thread(new Runnable(){
                @Override
                public void run() {
                    //模拟执行时间
                    System.out.println("当前线程："+Thread.currentThread().getName());
                    try {
                        for (Object obj : singleList) {
                            try {
                                //组装要执行的批量更新数据
                                JSONObject gasData = (JSONObject) obj;
                                // 查询商户
                                BsMerchant merchant = merchantService.getMerchant(gasData.getString("stationCode"));
                                if (merchant == null) {
                                    merchant = new BsMerchant();
                                    merchant.setStatus(MerchantStatusEnum.status1.getNumber());
                                }
                                merchant.setSourceType(MerchantSourceTypeEnum.type3.getNumber());
                                merchant.setProvinceCode(gasData.getLong("provinceId"));
                                merchant.setProvinceName(gasData.getString("provinceName"));
                                merchant.setCityCode(gasData.getLong("cityId"));
                                merchant.setCityName(gasData.getString("cityName"));
                                merchant.setAreaCode(gasData.getLong("districtId"));
                                merchant.setAreaName(gasData.getString("districtName"));
                                merchant.setMerNo(gasData.getString("stationCode"));
                                merchant.setMerName(gasData.getString("stationName"));
                                merchant.setMerLogo("https://oil.dctpay.com/filesystem/gas_logo_default.jpg");
                                merchant.setAddress(gasData.getString("stationAddress"));
                                merchant.setLongitude(gasData.getString("longitude"));
                                merchant.setLatitude(gasData.getString("latitude"));
                                merchant.setContactsName(merchant.getMerName());
                                merchant.setContactsTel(merchant.getMerNo());
                                merchant.setCustomerServiceTel("400-0236806");
                                merchant.setMerLabel(null);
                                if (merchant.getId() == null) {
                                    merchantService.createMerchant(merchant);
                                } else {
                                    merchantService.updateMerchant(merchant);
                                }

                                // 查询油站油价
                                List<BsGasOilPrice> gasOilPriceList = gasOilPriceService.getGasOilPriceList(merchant.getId());
                                if (!gasOilPriceList.isEmpty()) {
                                    BsGasOilPrice oilPriceExample = new BsGasOilPrice();
                                    oilPriceExample.setStatus(GasOilPriceStatusEnum.status2.getNumber());
                                    gasOilPriceService.batchUpdate(merchant.getMerNo(), oilPriceExample);
                                }
                                // 查询油站抢号
                                List<BsGasOilGunNo> oilGunNoList = gasOilGunNoService.getOilGunNoList(merchant.getMerNo());
                                for (BsGasOilGunNo gunNo : oilGunNoList) {
                                    gunNo.setStatus(0);
                                }

                                JSONArray oilPriceList = gasData.getJSONArray("oilPriceList");
                                for (Object oilPrice : oilPriceList) {
                                    JSONObject oilPriceObject = JSONObject.parseObject(JSONObject.toJSONString(oilPrice));
                                    // 查询油站油价
                                    List<BsGasOilPrice> oilPriceCollect = gasOilPriceList.stream().filter(o -> o.getOilNo().equals(oilPriceObject.getString("goodsCode"))).collect(Collectors.toList());
                                    BsGasOilPrice gasOilPrice = null;
                                    if (oilPriceCollect.isEmpty()) {
                                        gasOilPrice = new BsGasOilPrice();
                                        gasOilPrice.setMerId(merchant.getId());
                                        gasOilPrice.setMerNo(merchant.getMerNo());
                                        gasOilPrice.setOilNo(oilPriceObject.getString("goodsCode"));
                                        gasOilPrice.setOilNoName(oilPriceObject.getString("goodsCode")+"#");
                                        gasOilPrice.setStatus(GasOilPriceStatusEnum.status1.getNumber());
                                        // 油品类型  1:汽油:2:柴油;3:天然气
                                        if (oilPriceObject.getString("goodsGroupType").equals("GASOLINE")) {
                                            gasOilPrice.setOilType(1);
                                            gasOilPrice.setOilTypeName("汽油");
                                        } else if (oilPriceObject.getString("goodsGroupType").equals("DIESEL_OIL")) {
                                            gasOilPrice.setOilType(2);
                                            gasOilPrice.setOilTypeName("柴油");
                                        } else if (oilPriceObject.getString("goodsGroupType").equals("NATURAL_GAS")) {
                                            gasOilPrice.setOilType(3);
                                            gasOilPrice.setOilTypeName("天然气");
                                        }
                                    } else {
                                        gasOilPrice = oilPriceCollect.get(0);
                                        gasOilPrice.setStatus(GasOilPriceStatusEnum.status1.getNumber());
                                    }
                                    // 平台优惠
                                    gasOilPrice.setPreferentialMargin(new BigDecimal("0"));
                                    gasOilPrice.setPriceCost(oilPriceObject.getJSONObject("goodsPrice").getBigDecimal("amount"));
                                    gasOilPrice.setPriceVip(gasOilPrice.getPriceCost());
                                    gasOilPrice.setPriceGun(gasOilPrice.getPriceCost());
                                    gasOilPrice.setPriceOfficial(oilPriceObject.getJSONObject("listedPrice").getBigDecimal("amount"));
                                    // 国标价 - 油站价 = 油站直降
                                    gasOilPrice.setGasStationDrop(gasOilPrice.getPriceOfficial().subtract(gasOilPrice.getPriceCost()));
                                    gasOilPriceService.editOilPrice(gasOilPrice);

                                    for (Object gunNo : oilPriceObject.getJSONArray("oilGunNoList")) {
                                        // 查询抢号
                                        List<BsGasOilGunNo> gunNoCollect = oilGunNoList.stream()
                                                .filter(o -> o.getOilNo().equals(oilPriceObject.getString("goodsCode")) && o.getGunNo().equals(gunNo.toString()))
                                                .collect(Collectors.toList());
                                        // 如果没有找到抢号就新增一个
                                        BsGasOilGunNo gasOilGunNo = null;
                                        if (gunNoCollect.isEmpty()) {
                                            gasOilGunNo = new BsGasOilGunNo();
                                            gasOilGunNo.setGasOilPriceId(gasOilPrice.getId());
                                            gasOilGunNo.setMerId(gasOilPrice.getMerId());
                                            gasOilGunNo.setMerNo(gasOilPrice.getMerNo());
                                            gasOilGunNo.setOilNo(gasOilPrice.getOilNo());
                                            gasOilGunNo.setOilNoName(gasOilPrice.getOilNoName());
                                            gasOilGunNo.setOilType(gasOilPrice.getOilType());
                                            gasOilGunNo.setOilTypeName(gasOilPrice.getOilTypeName());
                                            gasOilGunNo.setGunNo(gunNo.toString());
                                            gasOilGunNo.setStatus(1);
                                            gasOilGunNo.setCreateTime(new Date());
                                            oilGunNoList.add(gasOilGunNo);
                                        } else {
                                            gasOilGunNo = gunNoCollect.get(0);
                                            gasOilGunNo.setStatus(1);
                                        }
                                    }
                                }

                                // 添加
                                gasOilGunNoService.batchInsert(oilGunNoList.stream().filter(o-> o.getId() == null).collect(Collectors.toList()));
                                // 更新
                                gasOilGunNoService.batchUpdate(oilGunNoList.stream().filter(o-> o.getId() != null && o.getStatus().equals(0)).collect(Collectors.toList()));
                                // 删除缓存
                                gasOilGunNoService.cleanCache(merchant.getMerNo());
                                // 清除油站缓存
                                gasService.clean(merchant.getMerNo());
                                // 通知代理
                                agentMerService.agentNotify(null, merchant.getMerNo());
                            } catch (Exception e) {
                                System.out.println("更新油站失败");
                            }
                        }

                    } catch (Exception e) {
                        System.out.println("更新油站出现异常");
                        System.out.println(e.getMessage());
                    } finally {
                        // 任务个数 - 1, 直至为0时唤醒await()
                        countDownLatch.countDown();
                    }
                }
            }));
        }
        try {
            // 让当前线程处于阻塞状态，直到锁存器计数为零
            countDownLatch.await();
        } catch (Exception e) {
            System.out.println("系统出现异常");
        }
        Long endTime = System.currentTimeMillis();
        Long useTime = endTime - startTime;
        System.out.println("本次更新任务结束,共计用时"+useTime+"毫秒");
    }

    /**
     * 拆分集合
     *
     * @param <T> 泛型对象
     * @param resList 需要拆分的集合
     * @param subListLength 每个子集合的元素个数
     * @return 返回拆分后的各个集合组成的列表
     **/
    public static <T> List<List<T>> splitList(List<T> resList, int subListLength) {
        if (CollectionUtils.isEmpty(resList) || subListLength <= 0) {
            return new ArrayList<>();
        }
        List<List<T>> ret = new ArrayList<>();
        int size = resList.size();
        if (size <= subListLength) {
            // 数据量不足 subListLength 指定的大小
            ret.add(resList);
        } else {
            int pre = size / subListLength;
            int last = size % subListLength;
            // 前面pre个集合，每个大小都是 subListLength 个元素
            for (int i = 0; i < pre; i++) {
                List<T> itemList = new ArrayList<>(subListLength);
                for (int j = 0; j < subListLength; j++) {
                    itemList.add(resList.get(i * subListLength + j));
                }
                ret.add(itemList);
            }

            // last的进行处理
            if (last > 0) {
                List<T> itemList = new ArrayList<>(last);
                for (int i = 0; i < last; i++) {
                    itemList.add(resList.get(pre * subListLength + i));
                }
                ret.add(itemList);
            }
        }
        return ret;
    }
}
