package com.social.media.domain.bot.valueobject;

import com.social.media.domain.shared.exception.BusinessRuleViolationException;

import java.time.LocalTime;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

/**
 * Value Object representing bot configuration settings
 */
public record BotConfiguration(
    Map<String, Object> settings,
    int maxActionsPerHour,
    int maxActionsPerDay,
    LocalTime startTime,
    LocalTime endTime,
    List<String> targetHashtags,
    List<String> excludeKeywords,
    boolean respectRateLimits,
    int delayBetweenActions
) {
    
    public BotConfiguration {
        settings = settings != null ? Map.copyOf(settings) : new HashMap<>();
        targetHashtags = targetHashtags != null ? List.copyOf(targetHashtags) : new ArrayList<>();
        excludeKeywords = excludeKeywords != null ? List.copyOf(excludeKeywords) : new ArrayList<>();
        
        if (maxActionsPerHour < 0) {
            throw new BusinessRuleViolationException("Max actions per hour cannot be negative");
        }
        if (maxActionsPerDay < 0) {
            throw new BusinessRuleViolationException("Max actions per day cannot be negative");
        }
        if (delayBetweenActions < 0) {
            throw new BusinessRuleViolationException("Delay between actions cannot be negative");
        }
        if (maxActionsPerHour > 0 && maxActionsPerDay > 0 && maxActionsPerHour * 24 > maxActionsPerDay) {
            throw new BusinessRuleViolationException("Daily limit should be consistent with hourly limit");
        }
    }
    
    public static BotConfiguration defaultConfiguration() {
        return new BotConfiguration(
            new HashMap<>(),
            10,  // 10 actions per hour
            100, // 100 actions per day
            LocalTime.of(9, 0),  // Start at 9 AM
            LocalTime.of(18, 0), // End at 6 PM
            new ArrayList<>(),
            new ArrayList<>(),
            true,
            30 // 30 seconds delay between actions
        );
    }
    
    public static BotConfiguration aggressive() {
        return new BotConfiguration(
            new HashMap<>(),
            20,  // 20 actions per hour
            300, // 300 actions per day
            LocalTime.of(8, 0),  // Start at 8 AM
            LocalTime.of(20, 0), // End at 8 PM
            new ArrayList<>(),
            new ArrayList<>(),
            true,
            15 // 15 seconds delay between actions
        );
    }
    
    public static BotConfiguration conservative() {
        return new BotConfiguration(
            new HashMap<>(),
            5,   // 5 actions per hour
            50,  // 50 actions per day
            LocalTime.of(10, 0), // Start at 10 AM
            LocalTime.of(16, 0), // End at 4 PM
            new ArrayList<>(),
            new ArrayList<>(),
            true,
            60 // 60 seconds delay between actions
        );
    }
    
    public boolean isWithinOperatingHours(LocalTime currentTime) {
        if (startTime == null || endTime == null) {
            return true; // No time restrictions
        }
        
        if (startTime.isBefore(endTime)) {
            // Same day operation (e.g., 9 AM to 6 PM)
            return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime);
        } else {
            // Overnight operation (e.g., 10 PM to 6 AM)
            return !currentTime.isBefore(startTime) || !currentTime.isAfter(endTime);
        }
    }
    
    public boolean hasTargetHashtags() {
        return !targetHashtags.isEmpty();
    }
    
    public boolean hasExcludeKeywords() {
        return !excludeKeywords.isEmpty();
    }
    
    public boolean shouldExcludeContent(String content) {
        if (content == null || excludeKeywords.isEmpty()) {
            return false;
        }
        
        String lowerContent = content.toLowerCase();
        return excludeKeywords.stream()
                .anyMatch(keyword -> lowerContent.contains(keyword.toLowerCase()));
    }
    
    public boolean matchesTargetHashtags(List<String> contentHashtags) {
        if (targetHashtags.isEmpty() || contentHashtags == null || contentHashtags.isEmpty()) {
            return targetHashtags.isEmpty(); // If no target hashtags, accept all
        }
        
        return contentHashtags.stream()
                .anyMatch(hashtag -> targetHashtags.contains(hashtag.toLowerCase()));
    }
    
    public Object getSetting(String key) {
        return settings.get(key);
    }
    
    public String getStringSetting(String key, String defaultValue) {
        Object value = settings.get(key);
        return value instanceof String ? (String) value : defaultValue;
    }
    
    public Integer getIntegerSetting(String key, Integer defaultValue) {
        Object value = settings.get(key);
        return value instanceof Integer ? (Integer) value : defaultValue;
    }
    
    public Boolean getBooleanSetting(String key, Boolean defaultValue) {
        Object value = settings.get(key);
        return value instanceof Boolean ? (Boolean) value : defaultValue;
    }
    
    public BotConfiguration withSetting(String key, Object value) {
        Map<String, Object> newSettings = new HashMap<>(this.settings);
        newSettings.put(key, value);
        return new BotConfiguration(
            newSettings, maxActionsPerHour, maxActionsPerDay,
            startTime, endTime, targetHashtags, excludeKeywords,
            respectRateLimits, delayBetweenActions
        );
    }
    
    public BotConfiguration withRateLimits(int maxPerHour, int maxPerDay) {
        return new BotConfiguration(
            settings, maxPerHour, maxPerDay,
            startTime, endTime, targetHashtags, excludeKeywords,
            respectRateLimits, delayBetweenActions
        );
    }
    
    public BotConfiguration withOperatingHours(LocalTime start, LocalTime end) {
        return new BotConfiguration(
            settings, maxActionsPerHour, maxActionsPerDay,
            start, end, targetHashtags, excludeKeywords,
            respectRateLimits, delayBetweenActions
        );
    }
    
    public BotConfiguration withTargetHashtags(List<String> hashtags) {
        return new BotConfiguration(
            settings, maxActionsPerHour, maxActionsPerDay,
            startTime, endTime, hashtags, excludeKeywords,
            respectRateLimits, delayBetweenActions
        );
    }
}
