package com.zsElectric.boot.charging.quartz;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo;
import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentPricePolicy;
import com.zsElectric.boot.charging.entity.ThirdPartyPolicyInfo;
import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper;
import com.zsElectric.boot.charging.mapper.ThirdPartyEquipmentPricePolicyMapper;
import com.zsElectric.boot.charging.mapper.ThirdPartyPolicyInfoMapper;
import com.zsElectric.boot.charging.service.ChargingBusinessService;
import com.zsElectric.boot.charging.vo.ChargingPricePolicyVO;
import com.zsElectric.boot.charging.vo.QueryStationsInfoVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 充电站信息同步定时任务
 *
 * @author system
 * @since 2025-12-11
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ChargingJob {

    private final ChargingBusinessService chargingBusinessService;
    private final ThirdPartyConnectorInfoMapper connectorInfoMapper;
    private final ThirdPartyEquipmentPricePolicyMapper pricePolicyMapper;
    private final ThirdPartyPolicyInfoMapper policyInfoMapper;
    
    // 任务执行标记，防止并发执行
    private volatile boolean isPricePolicySyncRunning = false;

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 同步充电站信息
     * 手动触发或启动时执行一次，从第三方接口获取充电站信息并存储到数据库
     * 注意：已移除定时任务，改为手动触发
     */
//     @Scheduled(cron = "0 0/30 * * * ?") // 已禁用定时执行
    public void syncStationsInfo() {
        log.info("开始执行充电站信息同步定时任务");
        
        try {
            // 获取当前时间作为查询时间
            String lastQueryTime = LocalDateTime.now().minusMinutes(30).format(FORMATTER);
            
            // 分页查询，每次查询100条
            Integer pageNo = 1;
            Integer pageSize = 100;
            
            log.info("查询参数 - LastQueryTime: {}, PageNo: {}, PageSize: {}", lastQueryTime, pageNo, pageSize);
            
            // 调用业务服务查询充电站信息（会自动保存到数据库）
            QueryStationsInfoVO result = chargingBusinessService.queryStationsInfo(lastQueryTime, pageNo, pageSize);
            
            if (result != null && result.getStationInfos() != null) {
                log.info("充电站信息同步完成，共同步 {} 个充电站", result.getStationInfos().size());
            } else {
                log.warn("充电站信息同步结果为空");
            }
            
        } catch (JsonProcessingException e) {
            log.error("充电站信息同步失败 - JSON处理异常", e);
        } catch (Exception e) {
            log.error("充电站信息同步失败 - 系统异常", e);
        }
        
        log.info("充电站信息同步定时任务执行结束");
    }

    /**
     * 定时同步设备价格策略信息
     * 每10分钟执行一次，查询所有充电桩的价格策略并存储到数据库
     * cron表达式: 0 10 * * * ? 表示每10分钟执行
     */
//    @Scheduled(cron = "0 */10 * * * ?")
    public void syncEquipmentPricePolicy() {
        // 检查任务是否正在执行，防止并发
        if (isPricePolicySyncRunning) {
            log.warn("价格策略同步任务正在执行中，跳过本次调度");
            return;
        }
        
        isPricePolicySyncRunning = true;
        log.info("开始执行设备价格策略同步定时任务");
        
        try {
            // 查询所有充电桩接口信息
            List<ThirdPartyConnectorInfo> connectorList = connectorInfoMapper.selectList(null);
            
            if (CollectionUtils.isEmpty(connectorList)) {
                log.warn("未查询到充电桩接口信息，跳过价格策略同步");
                return;
            }
            
            log.info("开始同步价格策略，总共 {} 个充电桩接口", connectorList.size());
            
            int successCount = 0;
            int failCount = 0;
            
            // 遍历每个充电桩接口，查询价格策略
            for (ThirdPartyConnectorInfo connector : connectorList) {
                try {
                    String connectorId = connector.getConnectorId();
                    String equipmentId = connector.getEquipmentId();
                    
                    // 检查该充电桩的价格策略上次更新时间，如果不足1小时则跳过
                    if (shouldSkipUpdate(connectorId)) {
                        log.info("充电桩价格策略上次更新时间不足1小时，跳过本次同步 - connectorId: {}, equipmentId: {}", 
                                connectorId, equipmentId);
                        continue; // 跳过本次充电桩，不调用第三方接口
                    }
                    
                    log.info("查询价格策略 - connectorId: {}, equipmentId: {}", connectorId, equipmentId);
                    
                    // 调用业务服务查询价格策略（会自动保存到数据库）
                    ChargingPricePolicyVO result = chargingBusinessService.queryEquipBusinessPolicy(equipmentId, connectorId);
                    
                    // 立即休眠10秒，避免触发第三方接口保护机制
                    // 第三方接口可能有频率限制，需要足够的间隔时间
//                    Thread.sleep(18000); // 10秒间隔
                    
                    if (result != null && result.getSuccStat() != null && result.getSuccStat() == 0) {
                        successCount++;
                        log.info("价格策略同步成功 - connectorId: {}, 时段数: {}", connectorId, result.getSumPeriod());
                    } else {
                        failCount++;
                        log.warn("价格策略同步失败 - connectorId: {}, 失败原因: {}, 跳过该接口继续处理下一个", connectorId, 
                                result != null ? result.getFailReason() : "返回结果为空");
                        continue; // 跳过失败的接口，继续处理下一个
                    }
                    
//                } catch (InterruptedException e) {
//                    Thread.currentThread().interrupt();
//                    log.error("线程休眠被中断 - connectorId: {}", connector.getConnectorId(), e);
//                    failCount++;
//                    break; // 中断后退出循环
                } catch (Exception e) {
                    failCount++;
                    log.error("同步价格策略失败 - connectorId: {}", connector.getConnectorId(), e);
                }
            }
            
            log.info("设备价格策略同步完成 - 成功: {}, 失败: {}, 总数: {}", successCount, failCount, connectorList.size());
            
        } catch (Exception e) {
            log.error("设备价格策略同步定时任务执行异常", e);
        } finally {
            // 确保任务执行完毕后释放锁
            isPricePolicySyncRunning = false;
            log.info("设备价格策略同步定时任务执行结束");
        }
    }
    
    /**
     * 检查是否应该跳过更新
     * 如果该充电桩的价格策略上次更新时间不足1小时，则跳过
     * 
     * @param connectorId 充电接口ID
     * @return true-跳过更新, false-需要更新
     */
    private boolean shouldSkipUpdate(String connectorId) {
        try {
            // 1. 查询该充电桩的最新价格策略记录
            ThirdPartyEquipmentPricePolicy latestPolicy = pricePolicyMapper.selectList(
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ThirdPartyEquipmentPricePolicy>()
                            .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, connectorId)
                            .orderByDesc(ThirdPartyEquipmentPricePolicy::getCreateTime)
                            .last("LIMIT 1")
            ).stream().findFirst().orElse(null);
            
            if (latestPolicy == null) {
                // 没有记录，需要更新
                return false;
            }
            
            // 2. 查询该价格策略的明细记录，获取最近的更新时间
            List<ThirdPartyPolicyInfo> policyInfoList = policyInfoMapper.selectList(
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ThirdPartyPolicyInfo>()
                            .eq(ThirdPartyPolicyInfo::getPricePolicyId, latestPolicy.getId())
                            .orderByDesc(ThirdPartyPolicyInfo::getUpdateTime)
                            .last("LIMIT 1")
            );
            
            if (policyInfoList.isEmpty()) {
                // 没有明细记录，需要更新
                return false;
            }
            
            LocalDateTime lastUpdateTime = policyInfoList.get(0).getUpdateTime();
            if (lastUpdateTime == null) {
                // 没有更新时间，需要更新
                return false;
            }
            
            // 3. 判断是否距离上次更新不足1小时
            LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);
            if (lastUpdateTime.isAfter(oneHourAgo)) {
                // 上次更新时间在1小时内，跳过更新
                log.debug("充电桩价格策略距离上次更新不足1小时 - connectorId: {}, lastUpdateTime: {}", 
                        connectorId, lastUpdateTime);
                return true;
            }
            
            // 距离上次更新超过1小时，需要更新
            return false;
            
        } catch (Exception e) {
            log.error("检查更新时间失败，默认需要更新 - connectorId: {}", connectorId, e);
            // 发生异常时，默认需要更新
            return false;
        }
    }
}
