package com.social.media.domain.entity;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;

import java.time.LocalDateTime;
import java.util.Objects;

@Entity
@Table(name = "posts", schema = "core_business",
       uniqueConstraints = {
           @UniqueConstraint(name = "posts_post_code_key", columnNames = {"post_code"})
       },
       indexes = {
           @Index(name = "idx_posts_author_id", columnList = "author_id"),
           @Index(name = "idx_posts_category_id", columnList = "category_id"),
           @Index(name = "idx_posts_company_id", columnList = "company_id"),
           @Index(name = "idx_posts_created_at", columnList = "created_at"),
           @Index(name = "idx_posts_is_pinned", columnList = "is_pinned"),
           @Index(name = "idx_posts_post_type", columnList = "post_type"),
           @Index(name = "idx_posts_published_at", columnList = "published_at"),
           @Index(name = "idx_posts_scheduled_for", columnList = "scheduled_for"),
           @Index(name = "idx_posts_status", columnList = "status")
       })
public class Post {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "post_code", nullable = false, unique = true, length = 20)
    private String postCode;
    
    @NotNull(message = "Company ID é obrigatório")
    @Column(name = "company_id", nullable = false)
    private Long companyId;
    
    @NotNull(message = "Author ID é obrigatório")
    @Column(name = "author_id", nullable = false)
    private Long authorId;
    
    @Column(name = "category_id")
    private Long categoryId;
    
    @Size(max = 65535, message = "Conteúdo deve ter no máximo 65535 caracteres")
    @Column(name = "content_text", columnDefinition = "TEXT")
    private String contentText;
    
    @NotNull(message = "Tipo do post é obrigatório")
    @Enumerated(EnumType.STRING)
    @Column(name = "post_type", nullable = false)
    private PostType postType = PostType.FEED;
    
    @NotNull(message = "Status do post é obrigatório")
    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false)
    private PostStatus status = PostStatus.DRAFT;
    
    @Column(name = "scheduled_for")
    private LocalDateTime scheduledFor;
    
    @Column(name = "published_at")
    private LocalDateTime publishedAt;
    
    @Size(max = 500, message = "Tags devem ter no máximo 500 caracteres")
    @Column(name = "tags", length = 500)
    private String tags;
    
    @NotNull(message = "Is pinned é obrigatório")
    @Column(name = "is_pinned", nullable = false)
    private Boolean isPinned = false;
    
    @Min(value = 0, message = "Contagem de visualizações deve ser no mínimo 0")
    @Column(name = "view_count", nullable = false)
    private Integer viewCount = 0;
    
    @Min(value = 0, message = "Contagem de likes deve ser no mínimo 0")
    @Column(name = "like_count", nullable = false)
    private Integer likeCount = 0;
    
    @Min(value = 0, message = "Contagem de compartilhamentos deve ser no mínimo 0")
    @Column(name = "share_count", nullable = false)
    private Integer shareCount = 0;
    
    @Min(value = 0, message = "Contagem de comentários deve ser no mínimo 0")
    @Column(name = "comment_count", nullable = false)
    private Integer commentCount = 0;
    
    @Column(name = "deleted_at")
    private LocalDateTime deletedAt;
    
    @Column(name = "created_at", nullable = false)
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
    
    // Enums
    public enum PostType {
        FEED, STORY, REEL, VIDEO, IMAGE, CAROUSEL
    }
    
    public enum PostStatus {
        DRAFT, SCHEDULED, PUBLISHED, FAILED, ARCHIVED
    }
    
    // Construtores
    public Post() {}
    
    public Post(Long companyId, Long authorId, String contentText) {
        this.companyId = companyId;
        this.authorId = authorId;
        this.contentText = contentText;
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    public Post(Long companyId, Long authorId, String contentText, PostType postType, PostStatus status) {
        this.companyId = companyId;
        this.authorId = authorId;
        this.contentText = contentText;
        this.postType = postType;
        this.status = status;
        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 (postType == null) {
            postType = PostType.FEED;
        }
        if (status == null) {
            status = PostStatus.DRAFT;
        }
        if (isPinned == null) {
            isPinned = false;
        }
        if (viewCount == null) {
            viewCount = 0;
        }
        if (likeCount == null) {
            likeCount = 0;
        }
        if (shareCount == null) {
            shareCount = 0;
        }
        if (commentCount == null) {
            commentCount = 0;
        }
    }
    
    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
    
    // Business methods
    public void publish() {
        this.status = PostStatus.PUBLISHED;
        this.publishedAt = LocalDateTime.now();
    }
    
    public void schedule(LocalDateTime scheduledTime) {
        if (scheduledTime.isBefore(LocalDateTime.now())) {
            throw new IllegalArgumentException("Scheduled time must be in the future");
        }
        this.status = PostStatus.SCHEDULED;
        this.scheduledFor = scheduledTime;
    }
    
    public void archive() {
        this.status = PostStatus.ARCHIVED;
        this.deletedAt = LocalDateTime.now();
    }
    
    public void pin() {
        this.isPinned = true;
    }
    
    public void unpin() {
        this.isPinned = false;
    }
    
    public void incrementViewCount() {
        this.viewCount++;
    }
    
    public void incrementLikeCount() {
        this.likeCount++;
    }
    
    public void decrementLikeCount() {
        if (this.likeCount > 0) {
            this.likeCount--;
        }
    }
    
    public void incrementShareCount() {
        this.shareCount++;
    }
    
    public void incrementCommentCount() {
        this.commentCount++;
    }
    
    public void decrementCommentCount() {
        if (this.commentCount > 0) {
            this.commentCount--;
        }
    }
    
    public boolean isPublished() {
        return status == PostStatus.PUBLISHED;
    }
    
    public boolean isScheduled() {
        return status == PostStatus.SCHEDULED;
    }
    
    public boolean isDraft() {
        return status == PostStatus.DRAFT;
    }
    
    public boolean isDeleted() {
        return deletedAt != null;
    }
    
    // Getters and Setters
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getPostCode() {
        return postCode;
    }
    
    public void setPostCode(String postCode) {
        this.postCode = postCode;
    }
    
    public Long getCompanyId() {
        return companyId;
    }
    
    public void setCompanyId(Long companyId) {
        this.companyId = companyId;
    }
    
    public Long getAuthorId() {
        return authorId;
    }
    
    public void setAuthorId(Long authorId) {
        this.authorId = authorId;
    }
    
    public Long getCategoryId() {
        return categoryId;
    }
    
    public void setCategoryId(Long categoryId) {
        this.categoryId = categoryId;
    }
    
    public String getContentText() {
        return contentText;
    }
    
    public void setContentText(String contentText) {
        this.contentText = contentText;
    }
    
    public PostType getPostType() {
        return postType;
    }
    
    public void setPostType(PostType postType) {
        this.postType = postType;
    }
    
    public PostStatus getStatus() {
        return status;
    }
    
    public void setStatus(PostStatus status) {
        this.status = status;
    }
    
    public LocalDateTime getScheduledFor() {
        return scheduledFor;
    }
    
    public void setScheduledFor(LocalDateTime scheduledFor) {
        this.scheduledFor = scheduledFor;
    }
    
    public LocalDateTime getPublishedAt() {
        return publishedAt;
    }
    
    public void setPublishedAt(LocalDateTime publishedAt) {
        this.publishedAt = publishedAt;
    }
    
    public String getTags() {
        return tags;
    }
    
    public void setTags(String tags) {
        this.tags = tags;
    }
    
    public Boolean getIsPinned() {
        return isPinned;
    }
    
    public void setIsPinned(Boolean isPinned) {
        this.isPinned = isPinned;
    }
    
    public Integer getViewCount() {
        return viewCount;
    }
    
    public void setViewCount(Integer viewCount) {
        this.viewCount = viewCount;
    }
    
    public Integer getLikeCount() {
        return likeCount;
    }
    
    public void setLikeCount(Integer likeCount) {
        this.likeCount = likeCount;
    }
    
    public Integer getShareCount() {
        return shareCount;
    }
    
    public void setShareCount(Integer shareCount) {
        this.shareCount = shareCount;
    }
    
    public Integer getCommentCount() {
        return commentCount;
    }
    
    public void setCommentCount(Integer commentCount) {
        this.commentCount = commentCount;
    }
    
    public LocalDateTime getDeletedAt() {
        return deletedAt;
    }
    
    public void setDeletedAt(LocalDateTime deletedAt) {
        this.deletedAt = deletedAt;
    }
    
    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;
        Post post = (Post) o;
        return Objects.equals(id, post.id) && Objects.equals(postCode, post.postCode);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, postCode);
    }
    
    @Override
    public String toString() {
        return "Post{" +
                "id=" + id +
                ", postCode='" + postCode + '\'' +
                ", companyId=" + companyId +
                ", authorId=" + authorId +
                ", postType=" + postType +
                ", status=" + status +
                ", createdAt=" + createdAt +
                '}';
    }
}
