package com.gree.mall.manager.schedule;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.gree.mall.manager.constant.Constant;
import com.gree.mall.manager.enums.IsEnum;
import com.gree.mall.manager.enums.admin.AdminWebsitTypeEnum;
import com.gree.mall.manager.enums.material.BuyPeopleEnum;
import com.gree.mall.manager.enums.material.PartsPushFlagEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.material.manage.WebsitPartsSalesLogic;
import com.gree.mall.manager.plus.entity.AdminWebsit;
import com.gree.mall.manager.plus.entity.WebsitPartsChangeSalesExec;
import com.gree.mall.manager.plus.entity.WebsitPartsRefundConfig;
import com.gree.mall.manager.plus.entity.WebsitPartsSales;
import com.gree.mall.manager.plus.service.AdminWebsitService;
import com.gree.mall.manager.plus.service.WebsitPartsRefundConfigService;
import com.gree.mall.manager.plus.service.WebsitPartsSalesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@Slf4j
public class NewPartsChangeSalesSchedule {

    @Value("${spring.profiles.active}")
    private String profiles;
    @Resource
    AdminWebsitService adminWebsitService;
    @Resource
    WebsitPartsRefundConfigService websitPartsRefundConfigService;
    @Resource
    WebsitPartsSalesService websitPartsSalesService;
    @Resource
    WebsitPartsSalesLogic websitPartsSalesLogic;
    @Resource
    RedisLockRegistry redisLockRegistry;

//    @Scheduled(cron = "0 0 01 * * ?")
    @Scheduled(initialDelay = 5000, fixedDelay = 30000)
    private void newPartsToSalesTasks() throws InterruptedException {
//        if (profiles.equals("dev") || !DateUtil.formatDateTime(DateUtil.date()).contains(" 01:0")) {
//            return;
//        }

        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.NEW_CHANGE + "add");

        if (!obtain.tryLock(10, TimeUnit.SECONDS)) {
            throw new RemoteServiceException("获取转销售添加锁失败");
        }
        try {
            // 第一步 查询配件网点
            List<AdminWebsit> websitList = adminWebsitService.lambdaQuery()
                    .isNotNull(AdminWebsit::getPartsWebsitId)
                    .eq(AdminWebsit::getType, AdminWebsitTypeEnum.C.getKey())
                    .list();

            final Map<String, List<AdminWebsit>> websitGroup = websitList.stream()
                    .collect(Collectors.groupingBy(AdminWebsit::getCompanyWechatId));

            for (Map.Entry<String, List<AdminWebsit>> entry : websitGroup.entrySet()) {
                final String companyId = entry.getKey();
                List<AdminWebsit> shopList = entry.getValue();
                // 第二步 查询配件返还配置
                WebsitPartsRefundConfig oneConfig = websitPartsRefundConfigService.lambdaQuery()
                        .eq(WebsitPartsRefundConfig::getCompanyWechatId, companyId)
                        .eq(WebsitPartsRefundConfig::getIsDefault, IsEnum.Y.getValue())
                        .one();
                List<WebsitPartsRefundConfig> partsConfigs = websitPartsRefundConfigService.lambdaQuery()
                        .eq(WebsitPartsRefundConfig::getCompanyWechatId, companyId)
                        .eq(WebsitPartsRefundConfig::getIsDefault, IsEnum.N.getValue())
                        .list();
                // 分组网点
                Map<String, WebsitPartsRefundConfig> refundConfigMap = partsConfigs.stream()
                        .collect(Collectors.toMap(WebsitPartsRefundConfig::getWebsitId, Function.identity()));

                DateTime curDate = DateUtil.beginOfDay(DateUtil.date());
                // 第三步 遍历查询已超期网点销售单
                for (AdminWebsit shop : shopList) {
                    if (Objects.isNull(shop.getPartsWebsitAttr())) {
                        // 未指定配件网点属性 false=外区 true内区
                        continue;
                    }
                    WebsitPartsRefundConfig partsConfig = refundConfigMap.get(shop.getWebsitId());
                    // 超期时间
                    Integer expire;
                    if (shop.getPartsWebsitAttr()) {
                        // 内区天数
                        expire = Objects.isNull(partsConfig) ? oneConfig.getNewRefundInner() : partsConfig.getNewRefundInner();
                    } else {
                        // 外区天数
                        expire = Objects.isNull(partsConfig) ? oneConfig.getNewRefundOutside() : partsConfig.getNewRefundOutside();
                    }

                    if (Objects.isNull(expire) || expire.compareTo(1) < 0) {
                        // 超期时间为空或少于1 不处理
                        continue;
                    }
                    // 查询未转销售单
                    List<WebsitPartsSales> salesOrders = websitPartsSalesService.lambdaQuery()
                            .eq(WebsitPartsSales::getCompanyWechatId, companyId)
                            .eq(WebsitPartsSales::getWebsitId, shop.getWebsitId())
                            .eq(WebsitPartsSales::getBuyPeople, BuyPeopleEnum.WORKER.getKey())
                            .eq(WebsitPartsSales::getPartsWebsitId, shop.getPartsWebsitId())
                            .eq(WebsitPartsSales::getPushFlag, PartsPushFlagEnum.SALES.getKey())
                            .list();
                    // 遍历未转销售单
                    for (WebsitPartsSales salesOrder : salesOrders) {
                        // 算出销售单超时时间
                        Date endTime = salesOrder.getEndTime();
                        DateTime offsetDateTime = DateUtil.offset(endTime, DateField.DAY_OF_MONTH, expire);
                        DateTime endOfDay = DateUtil.endOfDay(offsetDateTime);
                        if (endOfDay.getTime() < curDate.getTime()) {
                            // 销售单超时时间少于当前时间 pushFlag标志转为TRANS
                            try {
                                websitPartsSalesLogic.updatePartsSalesOrder(salesOrder);
                                WebsitPartsChangeSalesExec partsChangeSalesExec = new WebsitPartsChangeSalesExec();
                                partsChangeSalesExec.setExecTime(DateUtil.date())
                                        .setInfo("新件转销售作业处理成功,配件销售单：" + salesOrder.getId())
                                        .insert();
                            } catch (Exception e) {
                                WebsitPartsChangeSalesExec partsChangeSalesExec = new WebsitPartsChangeSalesExec();
                                partsChangeSalesExec.setExecTime(DateUtil.date())
                                        .setInfo("新件转销售作业处理出错,配件销售单：" + salesOrder.getId())
                                        .insert();
                                log.error("新件转销售作业处理出错,配件销售单：" + salesOrder.getId(), e);
                            }
                        }
                    }
                }
            }
        } catch(Exception e) {
            log.error("【新件转销售处理】失败",e);
            throw e;
        } finally {
            obtain.unlock();
        }

    }
}
