package com.social.media.domain.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

@Entity
@Table(name = "social_networks", schema = "core_business",
       uniqueConstraints = {
           @UniqueConstraint(name = "social_networks_network_code_key", columnNames = {"network_code"}),
           @UniqueConstraint(name = "social_networks_platform_key", columnNames = {"platform"})
       },
       indexes = {
           @Index(name = "idx_social_networks_is_active", columnList = "is_active"),
           @Index(name = "idx_social_networks_platform", columnList = "platform"),
           @Index(name = "idx_social_networks_sort_order", columnList = "sort_order")
       })
public class SocialNetwork {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "network_code", nullable = false, unique = true, length = 20)
    private String networkCode;
    
    @NotBlank(message = "Nome da rede social é obrigatório")
    @Size(max = 100, message = "Nome deve ter no máximo 100 caracteres")
    @Column(name = "name", nullable = false, length = 100)
    private String name;
    
    @NotBlank(message = "Plataforma é obrigatória")
    @Size(max = 50, message = "Plataforma deve ter no máximo 50 caracteres")
    @Column(name = "platform", nullable = false, unique = true, length = 50)
    private String platform;
    
    @Size(max = 500, message = "URL base da API deve ter no máximo 500 caracteres")
    @Column(name = "api_base_url", length = 500)
    private String apiBaseUrl;
    
    @Size(max = 20, message = "Versão da API deve ter no máximo 20 caracteres")
    @Column(name = "api_version", length = 20)
    private String apiVersion;
    
    @Size(max = 500, message = "URL OAuth deve ter no máximo 500 caracteres")
    @Column(name = "oauth_url", length = 500)
    private String oauthUrl;
    
    @Size(max = 500, message = "URL do webhook deve ter no máximo 500 caracteres")
    @Column(name = "webhook_url", length = 500)
    private String webhookUrl;
    
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "api_config", columnDefinition = "jsonb DEFAULT '{}'")
    private Map<String, Object> apiConfig;
    
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "rate_limits", columnDefinition = "jsonb DEFAULT '{\"perHour\": 1000, \"perMinute\": 60}'")
    private Map<String, Object> rateLimits;
    
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "supported_features", columnDefinition = "jsonb DEFAULT '{}'")
    private Map<String, Object> supportedFeatures;
    
    @NotNull(message = "Status ativo é obrigatório")
    @Column(name = "is_active", nullable = false)
    private Boolean isActive = true;
    
    @NotNull(message = "Flag de aprovação é obrigatória")
    @Column(name = "requires_approval", nullable = false)
    private Boolean requiresApproval = false;
    
    @Size(max = 500, message = "URL do logo deve ter no máximo 500 caracteres")
    @Column(name = "logo_url", length = 500)
    private String logoUrl;
    
    @Pattern(regexp = "^#[0-9A-Fa-f]{6}$", message = "Cor da marca deve estar no formato hexadecimal (#RRGGBB)")
    @Size(max = 7, message = "Cor da marca deve ter exatamente 7 caracteres")
    @Column(name = "brand_color", length = 7)
    private String brandColor;
    
    @NotNull(message = "Ordem de classificação é obrigatória")
    @Min(value = 0, message = "Ordem de classificação deve ser no mínimo 0")
    @Column(name = "sort_order", nullable = false)
    private Integer sortOrder = 0;
    
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    @Column(name = "created_by")
    private Long createdBy;
    
    @Column(name = "updated_by")
    private Long updatedBy;
    
    // Constructors
    public SocialNetwork() {
    }
    
    public SocialNetwork(String name, String platform) {
        this.name = name;
        this.platform = platform;
        this.isActive = true;
        this.requiresApproval = false;
        this.sortOrder = 0;
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    // Business methods
    
    /**
     * Checks if the social network supports a specific feature
     */
    public boolean supportsFeature(String featureName) {
        if (supportedFeatures == null) {
            return false;
        }
        return Boolean.TRUE.equals(supportedFeatures.get(featureName));
    }
    
    /**
     * Gets the rate limit for a specific type (perHour, perMinute, etc.)
     */
    public Integer getRateLimit(String limitType) {
        if (rateLimits == null) {
            return null;
        }
        Object limit = rateLimits.get(limitType);
        return limit instanceof Number ? ((Number) limit).intValue() : null;
    }
    
    /**
     * Gets an API configuration value
     */
    public Object getApiConfigValue(String key) {
        if (apiConfig == null) {
            return null;
        }
        return apiConfig.get(key);
    }
    
    /**
     * Sets an API configuration value
     */
    public void setApiConfigValue(String key, Object value) {
        if (apiConfig == null) {
            apiConfig = new java.util.HashMap<>();
        }
        apiConfig.put(key, value);
    }
    
    /**
     * Activates the social network
     */
    public void activate() {
        this.isActive = true;
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Deactivates the social network
     */
    public void deactivate() {
        this.isActive = false;
        this.updatedAt = LocalDateTime.now();
    }
    
    /**
     * Updates the sort order
     */
    public void updateSortOrder(Integer newOrder) {
        if (newOrder != null && newOrder >= 0) {
            this.sortOrder = newOrder;
            this.updatedAt = LocalDateTime.now();
        }
    }
    
    /**
     * Checks if the network is ready for production use
     */
    public boolean isReadyForProduction() {
        return isActive && 
               apiBaseUrl != null && !apiBaseUrl.trim().isEmpty() &&
               oauthUrl != null && !oauthUrl.trim().isEmpty();
    }
    
    /**
     * Gets the display name for UI purposes
     */
    public String getDisplayName() {
        return name != null ? name : platform;
    }
    
    // JPA Lifecycle callbacks
    
    @PrePersist
    protected void onCreate() {
        if (createdAt == null) {
            createdAt = LocalDateTime.now();
        }
        if (updatedAt == null) {
            updatedAt = LocalDateTime.now();
        }
        if (isActive == null) {
            isActive = true;
        }
        if (requiresApproval == null) {
            requiresApproval = false;
        }
        if (sortOrder == null) {
            sortOrder = 0;
        }
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    // Getters and Setters
    
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getNetworkCode() {
        return networkCode;
    }
    
    public void setNetworkCode(String networkCode) {
        this.networkCode = networkCode;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getPlatform() {
        return platform;
    }
    
    public void setPlatform(String platform) {
        this.platform = platform;
    }
    
    public String getApiBaseUrl() {
        return apiBaseUrl;
    }
    
    public void setApiBaseUrl(String apiBaseUrl) {
        this.apiBaseUrl = apiBaseUrl;
    }
    
    public String getApiVersion() {
        return apiVersion;
    }
    
    public void setApiVersion(String apiVersion) {
        this.apiVersion = apiVersion;
    }
    
    public String getOauthUrl() {
        return oauthUrl;
    }
    
    public void setOauthUrl(String oauthUrl) {
        this.oauthUrl = oauthUrl;
    }
    
    public String getWebhookUrl() {
        return webhookUrl;
    }
    
    public void setWebhookUrl(String webhookUrl) {
        this.webhookUrl = webhookUrl;
    }
    
    public Map<String, Object> getApiConfig() {
        return apiConfig;
    }
    
    public void setApiConfig(Map<String, Object> apiConfig) {
        this.apiConfig = apiConfig;
    }
    
    public Map<String, Object> getRateLimits() {
        return rateLimits;
    }
    
    public void setRateLimits(Map<String, Object> rateLimits) {
        this.rateLimits = rateLimits;
    }
    
    public Map<String, Object> getSupportedFeatures() {
        return supportedFeatures;
    }
    
    public void setSupportedFeatures(Map<String, Object> supportedFeatures) {
        this.supportedFeatures = supportedFeatures;
    }
    
    public Boolean getIsActive() {
        return isActive;
    }
    
    public void setIsActive(Boolean isActive) {
        this.isActive = isActive;
    }
    
    public Boolean getRequiresApproval() {
        return requiresApproval;
    }
    
    public void setRequiresApproval(Boolean requiresApproval) {
        this.requiresApproval = requiresApproval;
    }
    
    public String getLogoUrl() {
        return logoUrl;
    }
    
    public void setLogoUrl(String logoUrl) {
        this.logoUrl = logoUrl;
    }
    
    public String getBrandColor() {
        return brandColor;
    }
    
    public void setBrandColor(String brandColor) {
        this.brandColor = brandColor;
    }
    
    public Integer getSortOrder() {
        return sortOrder;
    }
    
    public void setSortOrder(Integer sortOrder) {
        this.sortOrder = sortOrder;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    
    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
    
    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }
    
    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }
    
    public Long getCreatedBy() {
        return createdBy;
    }
    
    public void setCreatedBy(Long createdBy) {
        this.createdBy = createdBy;
    }
    
    public Long getUpdatedBy() {
        return updatedBy;
    }
    
    public void setUpdatedBy(Long updatedBy) {
        this.updatedBy = updatedBy;
    }
    
    // equals, hashCode and toString
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        SocialNetwork that = (SocialNetwork) o;
        return Objects.equals(id, that.id) && 
               Objects.equals(platform, that.platform);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, platform);
    }
    
    @Override
    public String toString() {
        return "SocialNetwork{" +
                "id=" + id +
                ", networkCode='" + networkCode + '\'' +
                ", name='" + name + '\'' +
                ", platform='" + platform + '\'' +
                ", isActive=" + isActive +
                ", sortOrder=" + sortOrder +
                '}';
    }
}
