package com.social.media.domain.user;

import com.social.media.domain.shared.BaseValueObject;
import lombok.EqualsAndHashCode;
import lombok.Getter;

import java.time.ZoneId;
import java.util.*;

/**
 * Value Object representing user configuration and preferences.
 * 
 * Encapsulates all user-specific settings including language, timezone,
 * notification preferences, and dashboard configuration.
 * 
 * @author Social Media Manager Team
 * @version 2.0
 * @since 2025-01-01
 */
@Getter
@EqualsAndHashCode(callSuper = false)
public final class UserConfiguration extends BaseValueObject {
    
    // System settings
    private final String language;
    private final ZoneId timezone;
    private final String dateFormat;
    
    // Notification preferences
    private final NotificationPreferences notificationPreferences;
    
    // Dashboard configuration
    private final DashboardConfiguration dashboardConfiguration;
    
    /**
     * Creates a new UserConfiguration with all settings.
     */
    public UserConfiguration(String language, ZoneId timezone, String dateFormat,
                            NotificationPreferences notificationPreferences,
                            DashboardConfiguration dashboardConfiguration) {
        this.language = language != null ? language : "pt-BR";
        this.timezone = timezone != null ? timezone : ZoneId.of("America/Sao_Paulo");
        this.dateFormat = dateFormat != null ? dateFormat : "DD/MM/YYYY";
        this.notificationPreferences = notificationPreferences != null ? 
                                      notificationPreferences : NotificationPreferences.defaultPreferences();
        this.dashboardConfiguration = dashboardConfiguration != null ? 
                                     dashboardConfiguration : DashboardConfiguration.defaultConfiguration();
        
        super.validate();
    }
    
    /**
     * Creates a default configuration for new users.
     */
    public static UserConfiguration defaultConfiguration() {
        return new UserConfiguration("pt-BR", ZoneId.of("America/Sao_Paulo"), "DD/MM/YYYY",
                                    NotificationPreferences.defaultPreferences(),
                                    DashboardConfiguration.defaultConfiguration());
    }
    
    /**
     * Creates a new configuration with updated language.
     */
    public UserConfiguration withLanguage(String newLanguage) {
        return new UserConfiguration(newLanguage, timezone, dateFormat, 
                                    notificationPreferences, dashboardConfiguration);
    }
    
    /**
     * Creates a new configuration with updated timezone.
     */
    public UserConfiguration withTimezone(ZoneId newTimezone) {
        return new UserConfiguration(language, newTimezone, dateFormat, 
                                    notificationPreferences, dashboardConfiguration);
    }
    
    /**
     * Creates a new configuration with updated date format.
     */
    public UserConfiguration withDateFormat(String newDateFormat) {
        return new UserConfiguration(language, timezone, newDateFormat, 
                                    notificationPreferences, dashboardConfiguration);
    }
    
    /**
     * Creates a new configuration with updated notification preferences.
     */
    public UserConfiguration withNotificationPreferences(NotificationPreferences newPreferences) {
        return new UserConfiguration(language, timezone, dateFormat, 
                                    newPreferences, dashboardConfiguration);
    }
    
    /**
     * Creates a new configuration with updated dashboard configuration.
     */
    public UserConfiguration withDashboardConfiguration(DashboardConfiguration newDashboard) {
        return new UserConfiguration(language, timezone, dateFormat, 
                                    notificationPreferences, newDashboard);
    }
    
    @Override
    public void validate() {
        // Validate language format
        if (language == null || !language.matches("[a-z]{2}-[A-Z]{2}")) {
            throw new IllegalArgumentException("Language must be in format 'xx-XX' (e.g., 'pt-BR')");
        }
        
        // Validate timezone
        if (timezone == null) {
            throw new IllegalArgumentException("Timezone cannot be null");
        }
        
        // Validate date format
        if (dateFormat == null || dateFormat.trim().isEmpty()) {
            throw new IllegalArgumentException("Date format cannot be null or empty");
        }
        
        // Validate nested value objects
        if (notificationPreferences != null) {
            notificationPreferences.validate();
        }
        
        if (dashboardConfiguration != null) {
            dashboardConfiguration.validate();
        }
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        UserConfiguration that = (UserConfiguration) obj;
        return Objects.equals(language, that.language) &&
               Objects.equals(timezone, that.timezone) &&
               Objects.equals(dateFormat, that.dateFormat) &&
               Objects.equals(notificationPreferences, that.notificationPreferences) &&
               Objects.equals(dashboardConfiguration, that.dashboardConfiguration);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(language, timezone, dateFormat, notificationPreferences, dashboardConfiguration);
    }
    
    @Override
    public String toString() {
        return "UserConfiguration{" +
               "language='" + language + '\'' +
               ", timezone=" + timezone +
               ", dateFormat='" + dateFormat + '\'' +
               ", notificationPreferences=" + notificationPreferences +
               ", dashboardConfiguration=" + dashboardConfiguration +
               '}';
    }
    
    /**
     * Nested value object for notification preferences.
     */
    @Getter
    @EqualsAndHashCode
    public static final class NotificationPreferences {
        private final boolean emailNotifications;
        private final boolean pushNotifications;
        private final boolean smsNotifications;
        private final boolean postPublished;
        private final boolean postFailed;
        private final boolean accountDisconnected;
        private final boolean botCompleted;
        private final boolean botFailed;
        private final boolean weeklyReport;
        private final boolean monthlyReport;
        
        public NotificationPreferences(boolean emailNotifications, boolean pushNotifications,
                                     boolean smsNotifications, boolean postPublished,
                                     boolean postFailed, boolean accountDisconnected,
                                     boolean botCompleted, boolean botFailed,
                                     boolean weeklyReport, boolean monthlyReport) {
            this.emailNotifications = emailNotifications;
            this.pushNotifications = pushNotifications;
            this.smsNotifications = smsNotifications;
            this.postPublished = postPublished;
            this.postFailed = postFailed;
            this.accountDisconnected = accountDisconnected;
            this.botCompleted = botCompleted;
            this.botFailed = botFailed;
            this.weeklyReport = weeklyReport;
            this.monthlyReport = monthlyReport;
        }
        
        public static NotificationPreferences defaultPreferences() {
            return new NotificationPreferences(true, true, false, true, true, 
                                             true, true, true, false, false);
        }
        
        public void validate() {
            // No specific validation needed for boolean flags
        }
    }
    
    /**
     * Nested value object for dashboard configuration.
     */
    @Getter
    @EqualsAndHashCode
    public static final class DashboardConfiguration {
        private final String defaultView;
        private final int itemsPerPage;
        private final boolean showWelcomeMessage;
        private final List<String> favoriteMetrics;
        private final Set<String> hiddenWidgets;
        
        public DashboardConfiguration(String defaultView, int itemsPerPage, 
                                    boolean showWelcomeMessage, List<String> favoriteMetrics,
                                    Set<String> hiddenWidgets) {
            this.defaultView = defaultView != null ? defaultView : "overview";
            this.itemsPerPage = itemsPerPage > 0 ? itemsPerPage : 20;
            this.showWelcomeMessage = showWelcomeMessage;
            this.favoriteMetrics = favoriteMetrics != null ? 
                                  new ArrayList<>(favoriteMetrics) : 
                                  Arrays.asList("followers", "engagement", "reach");
            this.hiddenWidgets = hiddenWidgets != null ? 
                                new HashSet<>(hiddenWidgets) : new HashSet<>();
        }
        
        public static DashboardConfiguration defaultConfiguration() {
            return new DashboardConfiguration("overview", 20, true, 
                                             Arrays.asList("followers", "engagement", "reach"),
                                             new HashSet<>());
        }
        
        public void validate() {
            if (defaultView == null || defaultView.trim().isEmpty()) {
                throw new IllegalArgumentException("Default view cannot be null or empty");
            }
            
            if (itemsPerPage <= 0 || itemsPerPage > 100) {
                throw new IllegalArgumentException("Items per page must be between 1 and 100");
            }
            
            if (favoriteMetrics.size() > 10) {
                throw new IllegalArgumentException("Cannot have more than 10 favorite metrics");
            }
        }
    }
}
