package com.social.media.infrastructure.persistence.entity;

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * JPA Entity for Post aggregate
 */
@Data
@Entity
@Table(name = "posts", schema = "core_business")
@EntityListeners(AuditingEntityListener.class)
public class PostEntity {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    
    @Column(name = "company_id", nullable = false)
    private Long companyId;
    
    @Column(name = "author_id", nullable = false)
    private Long authorId;
    
    @Column(name = "category_id")
    private Long categoryId;
    
    @Column(name = "content_text", columnDefinition = "TEXT")
    private String contentText;
    
    @Enumerated(EnumType.STRING)
    @JdbcTypeCode(SqlTypes.NAMED_ENUM)
    @Column(name = "post_type", nullable = false, columnDefinition = "core_business.post_type")
    private PostTypeEntity postType;
    
    @Enumerated(EnumType.STRING)
    @JdbcTypeCode(SqlTypes.NAMED_ENUM)
    @Column(name = "status", nullable = false, columnDefinition = "core_business.post_status")
    private PostStatusEntity status;
    
    @ElementCollection
    @CollectionTable(
        name = "post_media",
        joinColumns = @JoinColumn(name = "post_id")
    )
    @Column(name = "media_id")
    private List<Long> mediaIds = new ArrayList<>();
    
    @ElementCollection
    @CollectionTable(
        name = "post_target_accounts",
        joinColumns = @JoinColumn(name = "post_id")
    )
    @Column(name = "social_account_id")
    private Set<Long> targetSocialAccountIds = new HashSet<>();
    
    @Column(name = "scheduled_for")
    private LocalDateTime scheduledFor;
    
    @Column(name = "published_at")
    private LocalDateTime publishedAt;
    
    @Column(name = "tags", length = 500)
    private String tags;
    
    @Column(name = "is_pinned", nullable = false)
    private boolean isPinned = false;
    
    @Column(name = "view_count", nullable = false)
    private int viewCount = 0;
    
    @Column(name = "like_count", nullable = false)
    private int likeCount = 0;
    
    @Column(name = "share_count", nullable = false)
    private int shareCount = 0;
    
    @Column(name = "comment_count", nullable = false)
    private int commentCount = 0;
    
    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    @LastModifiedDate
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;
    
    // Constructors
    public PostEntity() {}
    
    public PostEntity(Long id, Long companyId, Long authorId, Long categoryId,
                     String contentText, PostTypeEntity postType, PostStatusEntity status,
                     List<Long> mediaIds, Set<Long> targetSocialAccountIds,
                     LocalDateTime scheduledFor, LocalDateTime publishedAt, String tags,
                     boolean isPinned, int viewCount, int likeCount, int shareCount, int commentCount) {
        this.id = id;
        this.companyId = companyId;
        this.authorId = authorId;
        this.categoryId = categoryId;
        this.contentText = contentText;
        this.postType = postType;
        this.status = status;
        this.mediaIds = mediaIds != null ? new ArrayList<Long>(mediaIds) : new ArrayList<Long>();
        this.targetSocialAccountIds = targetSocialAccountIds != null ? new HashSet<Long>(targetSocialAccountIds) : new HashSet<Long>();
        this.scheduledFor = scheduledFor;
        this.publishedAt = publishedAt;
        this.tags = tags;
        this.isPinned = isPinned;
        this.viewCount = viewCount;
        this.likeCount = likeCount;
        this.shareCount = shareCount;
        this.commentCount = commentCount;
    }
    
    // Getters and Setters
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    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 PostTypeEntity getPostType() {
        return postType;
    }
    
    public void setPostType(PostTypeEntity postType) {
        this.postType = postType;
    }
    
    public PostStatusEntity getStatus() {
        return status;
    }
    
    public void setStatus(PostStatusEntity status) {
        this.status = status;
    }
    
    public List<Long> getMediaIds() {
        return mediaIds;
    }
    
    public void setMediaIds(List<Long> mediaIds) {
        this.mediaIds = mediaIds;
    }
    
    public Set<Long> getTargetSocialAccountIds() {
        return targetSocialAccountIds;
    }
    
    public void setTargetSocialAccountIds(Set<Long> targetSocialAccountIds) {
        this.targetSocialAccountIds = targetSocialAccountIds;
    }
    
    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 isPinned() {
        return isPinned;
    }
    
    public void setPinned(boolean pinned) {
        isPinned = pinned;
    }
    
    public int getViewCount() {
        return viewCount;
    }
    
    public void setViewCount(int viewCount) {
        this.viewCount = viewCount;
    }
    
    public int getLikeCount() {
        return likeCount;
    }
    
    public void setLikeCount(int likeCount) {
        this.likeCount = likeCount;
    }
    
    public int getShareCount() {
        return shareCount;
    }
    
    public void setShareCount(int shareCount) {
        this.shareCount = shareCount;
    }
    
    public int getCommentCount() {
        return commentCount;
    }
    
    public void setCommentCount(int commentCount) {
        this.commentCount = commentCount;
    }
    
    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;
    }
}
