package com.social.media.domain.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

@Entity
@Table(name = "campaign_targets", schema = "core_business",
       uniqueConstraints = {
           @UniqueConstraint(name = "campaign_targets_target_code_key", columnNames = {"target_code"}),
           @UniqueConstraint(name = "chk_campaign_targets_campaign_user_unique", 
                           columnNames = {"campaign_id", "user_name", "social_account_id"})
       },
       indexes = {
           @Index(name = "idx_campaign_targets_campaign_id", columnList = "campaign_id"),
           @Index(name = "idx_campaign_targets_social_account_id", columnList = "social_account_id"),
           @Index(name = "idx_campaign_targets_outreach_type", columnList = "outreach_type"),
           @Index(name = "idx_campaign_targets_outreach_status", columnList = "outreach_status"),
           @Index(name = "idx_campaign_targets_user_name", columnList = "user_name"),
           @Index(name = "idx_campaign_targets_source_type", columnList = "source_type"),
           @Index(name = "idx_campaign_targets_priority", columnList = "priority"),
           @Index(name = "idx_campaign_targets_scheduled_at", columnList = "scheduled_at"),
           @Index(name = "idx_campaign_targets_sent_at", columnList = "sent_at"),
           @Index(name = "idx_campaign_targets_is_active", columnList = "is_active"),
           @Index(name = "idx_campaign_targets_deleted", columnList = "deleted")
       })
public class CampaignTarget {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "target_code", nullable = false, unique = true, length = 20)
    private String targetCode;
    
    @NotNull(message = "Campaign ID é obrigatório")
    @Column(name = "campaign_id", nullable = false)
    private Long campaignId;
    
    @NotNull(message = "Social Account ID é obrigatório")
    @Column(name = "social_account_id", nullable = false)
    private Long socialAccountId;
    
    @NotBlank(message = "Nome é obrigatório")
    @Size(max = 255, message = "Nome deve ter no máximo 255 caracteres")
    @Column(name = "name", nullable = false, length = 255)
    private String name;
    
    @Column(name = "description", columnDefinition = "TEXT")
    private String description;
    
    @NotNull(message = "Tipo de outreach é obrigatório")
    @Enumerated(EnumType.STRING)
    @Column(name = "outreach_type", nullable = false)
    private OutreachType outreachType;
    
    @NotNull(message = "Status de outreach é obrigatório")
    @Enumerated(EnumType.STRING)
    @Column(name = "outreach_status", nullable = false)
    private OutreachStatus outreachStatus = OutreachStatus.PENDING;
    
    @NotBlank(message = "Nome de usuário é obrigatório")
    @Size(max = 255, message = "Nome de usuário deve ter no máximo 255 caracteres")
    @Column(name = "user_name", nullable = false, length = 255)
    private String userName;
    
    @Size(max = 1000, message = "URL do perfil deve ter no máximo 1000 caracteres")
    @Column(name = "profile_url", length = 1000)
    private String profileUrl;
    
    @Size(max = 1000, message = "URL da foto do perfil deve ter no máximo 1000 caracteres")
    @Column(name = "target_profile_photo_url", length = 1000)
    private String targetProfilePhotoUrl;
    
    @Column(name = "target_verified", nullable = false)
    private Boolean targetVerified = false;
    
    @Min(value = 0, message = "Número de seguidores deve ser no mínimo 0")
    @Column(name = "target_follower_count")
    private Integer targetFollowerCount = 0;
    
    @Min(value = 0, message = "Número de seguindo deve ser no mínimo 0")
    @Column(name = "target_following_count")
    private Integer targetFollowingCount = 0;
    
    @DecimalMin(value = "0.0", message = "Taxa de engajamento deve ser no mínimo 0.0")
    @DecimalMax(value = "100.0", message = "Taxa de engajamento deve ser no máximo 100.0")
    @Column(name = "target_engagement_rate", precision = 5, scale = 2)
    private BigDecimal targetEngagementRate = BigDecimal.ZERO;
    
    @Min(value = 1, message = "Prioridade deve ser no mínimo 1")
    @Max(value = 10, message = "Prioridade deve ser no máximo 10")
    @Column(name = "priority")
    private Integer priority = 5;
    
    @Column(name = "notes", columnDefinition = "TEXT")
    private String notes;
    
    @Column(name = "outreach_message", columnDefinition = "TEXT")
    private String outreachMessage;
    
    @Column(name = "response_message", columnDefinition = "TEXT")
    private String responseMessage;
    
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "interaction_data", columnDefinition = "jsonb")
    private Map<String, Object> interactionData;
    
    // Source tracking fields
    @Enumerated(EnumType.STRING)
    @Column(name = "source_type", length = 20)
    private SourceType sourceType;
    
    @Column(name = "source_follower_id")
    private Long sourceFollowerId;
    
    @Column(name = "source_following_id")
    private Long sourceFollowingId;
    
    // Timestamp fields
    @Column(name = "scheduled_at")
    private LocalDateTime scheduledAt;
    
    @Column(name = "sent_at")
    private LocalDateTime sentAt;
    
    @Column(name = "delivered_at")
    private LocalDateTime deliveredAt;
    
    @Column(name = "read_at")
    private LocalDateTime readAt;
    
    @Column(name = "replied_at")
    private LocalDateTime repliedAt;
    
    @Column(name = "failed_at")
    private LocalDateTime failedAt;
    
    @Column(name = "is_active", nullable = false)
    private Boolean isActive = true;
    
    @Column(name = "deleted", nullable = false)
    private Boolean deleted = false;
    
    @Column(name = "created_at", nullable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
    
    // Enums
    public enum OutreachType {
        DIRECT_MESSAGE, FEED_POST, STORY, REEL, COMMENT, LIKE, FOLLOW, EMAIL
    }
    
    public enum OutreachStatus {
        PENDING, SENT, DELIVERED, READ, REPLIED, FAILED, CANCELLED
    }
    
    public enum SourceType {
        FOLLOWER, FOLLOWING, MANUAL, IMPORTED
    }
    
    // Constructors
    public CampaignTarget() {}
    
    public CampaignTarget(Long campaignId, Long socialAccountId, String name, OutreachType outreachType, String userName) {
        this.campaignId = campaignId;
        this.socialAccountId = socialAccountId;
        this.name = name;
        this.outreachType = outreachType;
        this.userName = userName;
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    // Lifecycle callbacks
    @PrePersist
    protected void onCreate() {
        LocalDateTime now = LocalDateTime.now();
        if (createdAt == null) {
            createdAt = now;
        }
        updatedAt = now;
        
        // Set default values if not provided
        if (outreachStatus == null) {
            outreachStatus = OutreachStatus.PENDING;
        }
        if (targetVerified == null) {
            targetVerified = false;
        }
        if (targetFollowerCount == null) {
            targetFollowerCount = 0;
        }
        if (targetFollowingCount == null) {
            targetFollowingCount = 0;
        }
        if (targetEngagementRate == null) {
            targetEngagementRate = BigDecimal.ZERO;
        }
        if (priority == null) {
            priority = 5;
        }
        if (isActive == null) {
            isActive = true;
        }
        if (deleted == null) {
            deleted = false;
        }
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    // Business methods
    public void schedule(LocalDateTime scheduledTime) {
        this.scheduledAt = scheduledTime;
        this.outreachStatus = OutreachStatus.PENDING;
    }
    
    public void markAsSent() {
        this.sentAt = LocalDateTime.now();
        this.outreachStatus = OutreachStatus.SENT;
    }
    
    public void markAsDelivered() {
        this.deliveredAt = LocalDateTime.now();
        this.outreachStatus = OutreachStatus.DELIVERED;
    }
    
    public void markAsRead() {
        this.readAt = LocalDateTime.now();
        this.outreachStatus = OutreachStatus.READ;
    }
    
    public void markAsReplied(String responseMessage) {
        this.repliedAt = LocalDateTime.now();
        this.responseMessage = responseMessage;
        this.outreachStatus = OutreachStatus.REPLIED;
    }
    
    public void markAsFailed() {
        this.failedAt = LocalDateTime.now();
        this.outreachStatus = OutreachStatus.FAILED;
    }
    
    public void cancel() {
        this.outreachStatus = OutreachStatus.CANCELLED;
    }
    
    public void softDelete() {
        this.deleted = true;
        this.isActive = false;
    }
    
    public boolean isPending() {
        return outreachStatus == OutreachStatus.PENDING;
    }
    
    public boolean isSent() {
        return sentAt != null;
    }
    
    public boolean hasResponse() {
        return outreachStatus == OutreachStatus.REPLIED;
    }
    
    public boolean isHighPriority() {
        return priority != null && priority <= 3;
    }
    
    public boolean isInfluencerTarget() {
        return targetFollowerCount != null && targetFollowerCount >= 10000;
    }
    
    // Getters and Setters
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getTargetCode() {
        return targetCode;
    }
    
    public void setTargetCode(String targetCode) {
        this.targetCode = targetCode;
    }
    
    public Long getCampaignId() {
        return campaignId;
    }
    
    public void setCampaignId(Long campaignId) {
        this.campaignId = campaignId;
    }
    
    public Long getSocialAccountId() {
        return socialAccountId;
    }
    
    public void setSocialAccountId(Long socialAccountId) {
        this.socialAccountId = socialAccountId;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public OutreachType getOutreachType() {
        return outreachType;
    }
    
    public void setOutreachType(OutreachType outreachType) {
        this.outreachType = outreachType;
    }
    
    public OutreachStatus getOutreachStatus() {
        return outreachStatus;
    }
    
    public void setOutreachStatus(OutreachStatus outreachStatus) {
        this.outreachStatus = outreachStatus;
    }
    
    public String getUserName() {
        return userName;
    }
    
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    public String getProfileUrl() {
        return profileUrl;
    }
    
    public void setProfileUrl(String profileUrl) {
        this.profileUrl = profileUrl;
    }
    
    public String getTargetProfilePhotoUrl() {
        return targetProfilePhotoUrl;
    }
    
    public void setTargetProfilePhotoUrl(String targetProfilePhotoUrl) {
        this.targetProfilePhotoUrl = targetProfilePhotoUrl;
    }
    
    public Boolean getTargetVerified() {
        return targetVerified;
    }
    
    public void setTargetVerified(Boolean targetVerified) {
        this.targetVerified = targetVerified;
    }
    
    public Integer getTargetFollowerCount() {
        return targetFollowerCount;
    }
    
    public void setTargetFollowerCount(Integer targetFollowerCount) {
        this.targetFollowerCount = targetFollowerCount;
    }
    
    public Integer getTargetFollowingCount() {
        return targetFollowingCount;
    }
    
    public void setTargetFollowingCount(Integer targetFollowingCount) {
        this.targetFollowingCount = targetFollowingCount;
    }
    
    public BigDecimal getTargetEngagementRate() {
        return targetEngagementRate;
    }
    
    public void setTargetEngagementRate(BigDecimal targetEngagementRate) {
        this.targetEngagementRate = targetEngagementRate;
    }
    
    public Integer getPriority() {
        return priority;
    }
    
    public void setPriority(Integer priority) {
        this.priority = priority;
    }
    
    public String getNotes() {
        return notes;
    }
    
    public void setNotes(String notes) {
        this.notes = notes;
    }
    
    public String getOutreachMessage() {
        return outreachMessage;
    }
    
    public void setOutreachMessage(String outreachMessage) {
        this.outreachMessage = outreachMessage;
    }
    
    public String getResponseMessage() {
        return responseMessage;
    }
    
    public void setResponseMessage(String responseMessage) {
        this.responseMessage = responseMessage;
    }
    
    public Map<String, Object> getInteractionData() {
        return interactionData;
    }
    
    public void setInteractionData(Map<String, Object> interactionData) {
        this.interactionData = interactionData;
    }
    
    public SourceType getSourceType() {
        return sourceType;
    }
    
    public void setSourceType(SourceType sourceType) {
        this.sourceType = sourceType;
    }
    
    public Long getSourceFollowerId() {
        return sourceFollowerId;
    }
    
    public void setSourceFollowerId(Long sourceFollowerId) {
        this.sourceFollowerId = sourceFollowerId;
    }
    
    public Long getSourceFollowingId() {
        return sourceFollowingId;
    }
    
    public void setSourceFollowingId(Long sourceFollowingId) {
        this.sourceFollowingId = sourceFollowingId;
    }
    
    public LocalDateTime getScheduledAt() {
        return scheduledAt;
    }
    
    public void setScheduledAt(LocalDateTime scheduledAt) {
        this.scheduledAt = scheduledAt;
    }
    
    public LocalDateTime getSentAt() {
        return sentAt;
    }
    
    public void setSentAt(LocalDateTime sentAt) {
        this.sentAt = sentAt;
    }
    
    public LocalDateTime getDeliveredAt() {
        return deliveredAt;
    }
    
    public void setDeliveredAt(LocalDateTime deliveredAt) {
        this.deliveredAt = deliveredAt;
    }
    
    public LocalDateTime getReadAt() {
        return readAt;
    }
    
    public void setReadAt(LocalDateTime readAt) {
        this.readAt = readAt;
    }
    
    public LocalDateTime getRepliedAt() {
        return repliedAt;
    }
    
    public void setRepliedAt(LocalDateTime repliedAt) {
        this.repliedAt = repliedAt;
    }
    
    public LocalDateTime getFailedAt() {
        return failedAt;
    }
    
    public void setFailedAt(LocalDateTime failedAt) {
        this.failedAt = failedAt;
    }
    
    public Boolean getIsActive() {
        return isActive;
    }
    
    public void setIsActive(Boolean isActive) {
        this.isActive = isActive;
    }
    
    public Boolean getDeleted() {
        return deleted;
    }
    
    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }
    
    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;
    }
    
    // equals and hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CampaignTarget that = (CampaignTarget) o;
        return Objects.equals(id, that.id) && Objects.equals(targetCode, that.targetCode);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, targetCode);
    }
    
    @Override
    public String toString() {
        return "CampaignTarget{" +
                "id=" + id +
                ", targetCode='" + targetCode + '\'' +
                ", campaignId=" + campaignId +
                ", socialAccountId=" + socialAccountId +
                ", name='" + name + '\'' +
                ", userName='" + userName + '\'' +
                ", outreachType=" + outreachType +
                ", outreachStatus=" + outreachStatus +
                ", priority=" + priority +
                '}';
    }
}
