package com.qaup.collision.rule.service.impl;

import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.service.TimeWindowMatchingService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 时间窗口匹配服务实现类
 * 提供复杂的时间模式匹配和验证功能
 * 
 * @author AI Assistant
 * @version 1.0
 * @since 2025-01-17
 */
@Service
public class TimeWindowMatchingServiceImpl implements TimeWindowMatchingService {

    private static final Logger logger = LoggerFactory.getLogger(TimeWindowMatchingServiceImpl.class);

    @Autowired
    private ObjectMapper objectMapper;

    // 时间模式正则表达式
    private static final Pattern TIME_PATTERN = Pattern.compile("(\\d{2}):(\\d{2})-(\\d{2}):(\\d{2})");
    private static final Pattern WEEKDAY_PATTERN = Pattern.compile("(MON|TUE|WED|THU|FRI|SAT|SUN)(?:-(MON|TUE|WED|THU|FRI|SAT|SUN))?");
    private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{2})-(\\d{2})");

    // 星期映射
    private static final Map<String, Integer> WEEKDAY_MAP = Map.of(
        "MON", 1, "TUE", 2, "WED", 3, "THU", 4, "FRI", 5, "SAT", 6, "SUN", 7
    );

    @Override
    public boolean isRuleEffectiveAtTime(SpatialRule rule, LocalDateTime timestamp) {
        try {
            // 1. 检查总体有效期
            if (rule.getEffectiveStartTime() != null && timestamp.isBefore(rule.getEffectiveStartTime())) {
                return false;
            }
            
            if (rule.getEffectiveEndTime() != null && timestamp.isAfter(rule.getEffectiveEndTime())) {
                return false;
            }

            // 2. 检查基本时间窗口
            if (rule.getDailyStartTime() != null || rule.getDailyEndTime() != null || rule.getWeekdayPattern() != null) {
                if (!matchesBasicTimeWindow(rule.getDailyStartTime(), rule.getDailyEndTime(), 
                                           rule.getWeekdayPattern(), timestamp)) {
                    return false;
                }
            }

            // 3. 检查复杂时间模式
            if (rule.getTimePatterns() != null) {
                return matchesComplexTimePatterns(rule.getTimePatterns(), timestamp);
            }

            return true;

        } catch (Exception e) {
            logger.error("检查规则时间有效性失败: ruleId={}, timestamp={}", rule.getRuleId(), timestamp, e);
            return false;
        }
    }

    @Override
    public boolean matchesBasicTimeWindow(LocalTime dailyStartTime, LocalTime dailyEndTime, 
                                         Integer weekdayPattern, LocalDateTime timestamp) {
        try {
            // 1. 检查每日时间范围
            if (dailyStartTime != null && dailyEndTime != null) {
                if (!matchesDailyTimeRange(dailyStartTime, dailyEndTime, timestamp.toLocalTime())) {
                    return false;
                }
            }

            // 2. 检查星期模式
            if (weekdayPattern != null) {
                if (!matchesWeekdayPattern(weekdayPattern, timestamp)) {
                    return false;
                }
            }

            return true;

        } catch (Exception e) {
            logger.error("基本时间窗口匹配失败: dailyStart={}, dailyEnd={}, weekdayPattern={}, timestamp={}", 
                        dailyStartTime, dailyEndTime, weekdayPattern, timestamp, e);
            return false;
        }
    }

    @Override
    public boolean matchesComplexTimePatterns(JsonNode timePatterns, LocalDateTime timestamp) {
        try {
            if (timePatterns == null || timePatterns.isNull()) {
                return true;
            }

            // 处理数组形式的时间模式
            if (timePatterns.isArray()) {
                // 如果是空数组，表示没有时间限制，应该返回true
                if (timePatterns.size() == 0) {
                    return true;
                }
                
                for (JsonNode pattern : timePatterns) {
                    if (matchesSingleTimePattern(pattern, timestamp)) {
                        return true; // 任一模式匹配即可
                    }
                }
                return false;
            }

            // 处理单个时间模式对象
            return matchesSingleTimePattern(timePatterns, timestamp);

        } catch (Exception e) {
            logger.error("复杂时间模式匹配失败: patterns={}, timestamp={}", timePatterns, timestamp, e);
            return false;
        }
    }

    @Override
    public boolean matchesComplexTimePatterns(String timePatternsJson, LocalDateTime timestamp) {
        try {
            if (timePatternsJson == null || timePatternsJson.trim().isEmpty()) {
                return true;
            }
            JsonNode timePatterns = objectMapper.readTree(timePatternsJson);
            return matchesComplexTimePatterns(timePatterns, timestamp);
        } catch (Exception e) {
            logger.error("解析时间模式JSON失败: json={}, timestamp={}", timePatternsJson, timestamp, e);
            return false;
        }
    }

    @Override
    public boolean matchesDailyTimeRange(LocalTime startTime, LocalTime endTime, LocalTime currentTime) {
        if (startTime == null || endTime == null || currentTime == null) {
            return true;
        }

        if (startTime.isBefore(endTime)) {
            // 正常时间范围（如 08:00-18:00）
            return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime);
        } else {
            // 跨日时间范围（如 22:00-06:00）
            return !currentTime.isAfter(endTime) || !currentTime.isBefore(startTime);
        }
    }

    @Override
    public boolean matchesWeekdayPattern(Integer weekdayPattern, LocalDateTime timestamp) {
        if (weekdayPattern == null) {
            return true;
        }

        int dayOfWeek = timestamp.getDayOfWeek().getValue(); // 1=Monday, 7=Sunday
        int dayBit = 1 << (dayOfWeek - 1); // 转换为位掩码
        
        return (weekdayPattern & dayBit) != 0;
    }

    @Override
    public boolean matchesMonthPattern(Integer monthPattern, LocalDateTime timestamp) {
        if (monthPattern == null) {
            return true;
        }

        int month = timestamp.getMonthValue(); // 1=January, 12=December
        int monthBit = 1 << (month - 1); // 转换为位掩码
        
        return (monthPattern & monthBit) != 0;
    }

    @Override
    public boolean matchesDateRange(String startDate, String endDate, LocalDateTime timestamp) {
        try {
            if (startDate == null || endDate == null) {
                return true;
            }

            // 解析日期格式 MM-dd
            String[] startParts = startDate.split("-");
            String[] endParts = endDate.split("-");
            
            if (startParts.length != 2 || endParts.length != 2) {
                logger.warn("日期格式错误: startDate={}, endDate={}", startDate, endDate);
                return true;
            }

            int startMonth = Integer.parseInt(startParts[0]);
            int startDay = Integer.parseInt(startParts[1]);
            int endMonth = Integer.parseInt(endParts[0]);
            int endDay = Integer.parseInt(endParts[1]);

            int currentMonth = timestamp.getMonthValue();
            int currentDay = timestamp.getDayOfMonth();

            // 构造比较用的数值（MMDD格式）
            int startValue = startMonth * 100 + startDay;
            int endValue = endMonth * 100 + endDay;
            int currentValue = currentMonth * 100 + currentDay;

            if (startValue <= endValue) {
                // 正常日期范围（如 03-15 到 11-30）
                return currentValue >= startValue && currentValue <= endValue;
            } else {
                // 跨年日期范围（如 11-15 到 03-15）
                return currentValue >= startValue || currentValue <= endValue;
            }

        } catch (Exception e) {
            logger.error("日期范围匹配失败: startDate={}, endDate={}, timestamp={}", startDate, endDate, timestamp, e);
            return true; // 出错时默认匹配
        }
    }

    @Override
    public boolean matchesIntervalPattern(Integer intervalMinutes, Integer offsetMinutes, LocalDateTime timestamp) {
        if (intervalMinutes == null || intervalMinutes <= 0) {
            return true;
        }

        try {
            // 计算从一天开始的分钟数
            int minutesFromDayStart = timestamp.getHour() * 60 + timestamp.getMinute();
            
            // 应用偏移
            int offset = offsetMinutes != null ? offsetMinutes : 0;
            int adjustedMinutes = minutesFromDayStart - offset;
            
            // 检查是否符合间隔模式
            return adjustedMinutes >= 0 && (adjustedMinutes % intervalMinutes) == 0;

        } catch (Exception e) {
            logger.error("间隔模式匹配失败: interval={}, offset={}, timestamp={}", 
                        intervalMinutes, offsetMinutes, timestamp, e);
            return true;
        }
    }

    @Override
    public boolean matchesHolidayPattern(JsonNode holidayPattern, LocalDateTime timestamp) {
        try {
            if (holidayPattern == null || holidayPattern.isNull()) {
                return true;
            }

            // 获取节假日配置
            boolean includeHolidays = holidayPattern.path("include").asBoolean(true);
            boolean excludeHolidays = holidayPattern.path("exclude").asBoolean(false);
            
            // 检查是否为节假日（这里需要集成节假日服务）
            boolean isHoliday = isHolidayDate(timestamp);
            
            if (excludeHolidays && isHoliday) {
                return false;
            }
            
            if (!includeHolidays && isHoliday) {
                return false;
            }
            
            return true;

        } catch (Exception e) {
            logger.error("节假日模式匹配失败: pattern={}, timestamp={}", holidayPattern, timestamp, e);
            return true;
        }
    }

    @Override
    public boolean matchesHolidayPattern(String holidayPatternJson, LocalDateTime timestamp) {
        try {
            if (holidayPatternJson == null || holidayPatternJson.trim().isEmpty()) {
                return true;
            }
            JsonNode holidayPattern = objectMapper.readTree(holidayPatternJson);
            return matchesHolidayPattern(holidayPattern, timestamp);
        } catch (Exception e) {
            logger.error("解析节假日模式JSON失败: json={}, timestamp={}", holidayPatternJson, timestamp, e);
            return false;
        }
    }

    @Override
    public boolean matchesSpecialDates(List<String> specialDates, LocalDateTime timestamp) {
        if (specialDates == null || specialDates.isEmpty()) {
            return true;
        }

        try {
            String currentDate = timestamp.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String currentMonthDay = timestamp.format(DateTimeFormatter.ofPattern("MM-dd"));
            
            return specialDates.contains(currentDate) || specialDates.contains(currentMonthDay);

        } catch (Exception e) {
            logger.error("特殊日期匹配失败: specialDates={}, timestamp={}", specialDates, timestamp, e);
            return true;
        }
    }

    @Override
    public LocalDateTime getNextEffectiveTime(SpatialRule rule, LocalDateTime fromTime) {
        // TODO: 实现获取下次生效时间的复杂逻辑
        logger.debug("获取下次生效时间功能待实现: ruleId={}, fromTime={}", rule.getRuleId(), fromTime);
        return null;
    }

    @Override
    public LocalDateTime getNextIneffectiveTime(SpatialRule rule, LocalDateTime fromTime) {
        // TODO: 实现获取下次失效时间的复杂逻辑
        logger.debug("获取下次失效时间功能待实现: ruleId={}, fromTime={}", rule.getRuleId(), fromTime);
        return null;
    }

    @Override
    public long calculateEffectiveDuration(SpatialRule rule, LocalDateTime startTime, LocalDateTime endTime) {
        // TODO: 实现计算有效时长的复杂逻辑
        logger.debug("计算有效时长功能待实现: ruleId={}, startTime={}, endTime={}", 
                    rule.getRuleId(), startTime, endTime);
        return 0;
    }

    @Override
    public List<TimeWindow> getEffectiveTimeWindows(SpatialRule rule, LocalDateTime date) {
        // TODO: 实现获取有效时间段的复杂逻辑
        logger.debug("获取有效时间段功能待实现: ruleId={}, date={}", rule.getRuleId(), date);
        return new ArrayList<>();
    }

    @Override
    public TimePatternValidationResult validateTimePatterns(JsonNode timePatterns) {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();

        try {
            if (timePatterns == null || timePatterns.isNull()) {
                return new TimePatternValidationResult(true, errors, warnings);
            }

            if (timePatterns.isArray()) {
                for (int i = 0; i < timePatterns.size(); i++) {
                    validateSingleTimePattern(timePatterns.get(i), "pattern[" + i + "]", errors, warnings);
                }
            } else {
                validateSingleTimePattern(timePatterns, "pattern", errors, warnings);
            }

        } catch (Exception e) {
            errors.add("时间模式验证异常: " + e.getMessage());
        }

        return new TimePatternValidationResult(errors.isEmpty(), errors, warnings);
    }

    @Override
    public TimePatternValidationResult validateTimePatterns(String timePatternsJson) {
        try {
            if (timePatternsJson == null || timePatternsJson.trim().isEmpty()) {
                return new TimePatternValidationResult(true, Collections.emptyList(), Collections.emptyList());
            }
            JsonNode timePatterns = objectMapper.readTree(timePatternsJson);
            return validateTimePatterns(timePatterns);
        } catch (Exception e) {
            logger.error("解析时间模式JSON失败: json={}", timePatternsJson, e);
            List<String> errors = Arrays.asList("JSON格式错误: " + e.getMessage());
            return new TimePatternValidationResult(false, errors, Collections.emptyList());
        }
    }

    @Override
    public ParsedTimePattern parseTimePatternString(String timePatternString) {
        try {
            if (timePatternString == null || timePatternString.trim().isEmpty()) {
                return null;
            }

            List<Integer> weekdays = new ArrayList<>();
            LocalTime startTime = null;
            LocalTime endTime = null;
            List<String> specialDates = new ArrayList<>();
            boolean excludeHolidays = false;

            String[] parts = timePatternString.trim().split("\\s+");
            
            for (String part : parts) {
                // 解析星期模式
                Matcher weekdayMatcher = WEEKDAY_PATTERN.matcher(part);
                if (weekdayMatcher.matches()) {
                    String startDay = weekdayMatcher.group(1);
                    String endDay = weekdayMatcher.group(2);
                    
                    if (endDay != null) {
                        // 范围模式（如 MON-FRI）
                        int start = WEEKDAY_MAP.get(startDay);
                        int end = WEEKDAY_MAP.get(endDay);
                        
                        if (start <= end) {
                            for (int i = start; i <= end; i++) {
                                weekdays.add(i);
                            }
                        } else {
                            // 跨周范围（如 SAT-MON）
                            for (int i = start; i <= 7; i++) {
                                weekdays.add(i);
                            }
                            for (int i = 1; i <= end; i++) {
                                weekdays.add(i);
                            }
                        }
                    } else {
                        // 单个星期
                        weekdays.add(WEEKDAY_MAP.get(startDay));
                    }
                    continue;
                }

                // 解析时间模式
                Matcher timeMatcher = TIME_PATTERN.matcher(part);
                if (timeMatcher.matches()) {
                    int startHour = Integer.parseInt(timeMatcher.group(1));
                    int startMinute = Integer.parseInt(timeMatcher.group(2));
                    int endHour = Integer.parseInt(timeMatcher.group(3));
                    int endMinute = Integer.parseInt(timeMatcher.group(4));
                    
                    startTime = LocalTime.of(startHour, startMinute);
                    endTime = LocalTime.of(endHour, endMinute);
                    continue;
                }

                // 解析特殊标记
                if ("EXCLUDE_HOLIDAYS".equals(part)) {
                    excludeHolidays = true;
                    continue;
                }

                // 解析日期模式
                Matcher dateMatcher = DATE_PATTERN.matcher(part);
                if (dateMatcher.matches()) {
                    specialDates.add(part);
                }
            }

            return new ParsedTimePattern(weekdays, startTime, endTime, specialDates, excludeHolidays);

        } catch (Exception e) {
            logger.error("解析时间模式字符串失败: pattern={}", timePatternString, e);
            return null;
        }
    }

    // ============================================
    // 私有辅助方法
    // ============================================

    private boolean matchesSingleTimePattern(JsonNode pattern, LocalDateTime timestamp) {
        try {
            // 检查时间范围
            if (pattern.has("timeRange")) {
                JsonNode timeRange = pattern.get("timeRange");
                String startTimeStr = timeRange.path("start").asText();
                String endTimeStr = timeRange.path("end").asText();
                
                if (!startTimeStr.isEmpty() && !endTimeStr.isEmpty()) {
                    LocalTime startTime = LocalTime.parse(startTimeStr);
                    LocalTime endTime = LocalTime.parse(endTimeStr);
                    
                    if (!matchesDailyTimeRange(startTime, endTime, timestamp.toLocalTime())) {
                        return false;
                    }
                }
            }

            // 检查星期模式
            if (pattern.has("weekdays")) {
                JsonNode weekdays = pattern.get("weekdays");
                if (weekdays.isArray()) {
                    boolean weekdayMatch = false;
                    int currentWeekday = timestamp.getDayOfWeek().getValue();
                    
                    for (JsonNode weekday : weekdays) {
                        if (weekday.asInt() == currentWeekday) {
                            weekdayMatch = true;
                            break;
                        }
                    }
                    
                    if (!weekdayMatch) {
                        return false;
                    }
                }
            }

            // 检查月份模式
            if (pattern.has("months")) {
                JsonNode months = pattern.get("months");
                if (months.isArray()) {
                    boolean monthMatch = false;
                    int currentMonth = timestamp.getMonthValue();
                    
                    for (JsonNode month : months) {
                        if (month.asInt() == currentMonth) {
                            monthMatch = true;
                            break;
                        }
                    }
                    
                    if (!monthMatch) {
                        return false;
                    }
                }
            }

            // 检查日期范围
            if (pattern.has("dateRange")) {
                JsonNode dateRange = pattern.get("dateRange");
                String startDate = dateRange.path("start").asText();
                String endDate = dateRange.path("end").asText();
                
                if (!startDate.isEmpty() && !endDate.isEmpty()) {
                    if (!matchesDateRange(startDate, endDate, timestamp)) {
                        return false;
                    }
                }
            }

            // 检查特殊日期
            if (pattern.has("specialDates")) {
                JsonNode specialDates = pattern.get("specialDates");
                if (specialDates.isArray()) {
                    List<String> dateList = new ArrayList<>();
                    for (JsonNode date : specialDates) {
                        dateList.add(date.asText());
                    }
                    
                    if (!matchesSpecialDates(dateList, timestamp)) {
                        return false;
                    }
                }
            }

            // 检查节假日模式
            if (pattern.has("holidays")) {
                if (!matchesHolidayPattern(pattern.get("holidays"), timestamp)) {
                    return false;
                }
            }

            return true;

        } catch (Exception e) {
            logger.error("单个时间模式匹配失败: pattern={}, timestamp={}", pattern, timestamp, e);
            return false;
        }
    }

    private void validateSingleTimePattern(JsonNode pattern, String patternName, 
                                          List<String> errors, List<String> warnings) {
        try {
            // 验证时间范围格式
            if (pattern.has("timeRange")) {
                JsonNode timeRange = pattern.get("timeRange");
                String startTimeStr = timeRange.path("start").asText();
                String endTimeStr = timeRange.path("end").asText();
                
                if (!startTimeStr.isEmpty()) {
                    try {
                        LocalTime.parse(startTimeStr);
                    } catch (DateTimeParseException e) {
                        errors.add(patternName + ".timeRange.start 格式错误: " + startTimeStr);
                    }
                }
                
                if (!endTimeStr.isEmpty()) {
                    try {
                        LocalTime.parse(endTimeStr);
                    } catch (DateTimeParseException e) {
                        errors.add(patternName + ".timeRange.end 格式错误: " + endTimeStr);
                    }
                }
            }

            // 验证星期数组
            if (pattern.has("weekdays")) {
                JsonNode weekdays = pattern.get("weekdays");
                if (weekdays.isArray()) {
                    for (JsonNode weekday : weekdays) {
                        int day = weekday.asInt();
                        if (day < 1 || day > 7) {
                            errors.add(patternName + ".weekdays 包含无效值: " + day + "（应为1-7）");
                        }
                    }
                } else {
                    errors.add(patternName + ".weekdays 应为数组格式");
                }
            }

            // 验证月份数组
            if (pattern.has("months")) {
                JsonNode months = pattern.get("months");
                if (months.isArray()) {
                    for (JsonNode month : months) {
                        int m = month.asInt();
                        if (m < 1 || m > 12) {
                            errors.add(patternName + ".months 包含无效值: " + m + "（应为1-12）");
                        }
                    }
                } else {
                    errors.add(patternName + ".months 应为数组格式");
                }
            }

        } catch (Exception e) {
            errors.add(patternName + " 验证异常: " + e.getMessage());
        }
    }

    private boolean isHolidayDate(LocalDateTime timestamp) {
        // TODO: 集成节假日服务或数据库查询
        // 这里可以集成第三方节假日API或维护节假日数据表
        logger.debug("节假日检查功能待实现: timestamp={}", timestamp);
        return false; // 暂时返回false
    }
} 