package com.social.media.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

import java.time.LocalDateTime;

/**
 * Data Transfer Object for PostMedia relationships
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PostMediaDto {
    
    private Long id;
    
    @NotNull(message = "Post ID is required")
    @Positive(message = "Post ID must be positive")
    @JsonProperty("post_id")
    private Long postId;
    
    @NotNull(message = "Media ID is required")
    @Positive(message = "Media ID must be positive")
    @JsonProperty("media_id")
    private Long mediaId;
    
    @NotNull(message = "Display order is required")
    @Positive(message = "Display order must be positive")
    @JsonProperty("display_order")
    private Integer displayOrder;
    
    @NotNull(message = "Primary status is required")
    @JsonProperty("is_primary")
    private Boolean isPrimary;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonProperty("created_at")
    private LocalDateTime createdAt;
    
    // Nested objects for full information (optional)
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private PostDto post;
    
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private MediaDto media;
    
    // Computed fields
    @JsonProperty("is_valid")
    public Boolean getIsValid() {
        return postId != null && mediaId != null && 
               displayOrder != null && displayOrder > 0;
    }
    
    @JsonProperty("can_move_up")
    public Boolean getCanMoveUp() {
        return displayOrder != null && displayOrder > 1;
    }
    
    @JsonProperty("can_move_down")
    public Boolean getCanMoveDown() {
        return displayOrder != null; // Can always move down (increases order)
    }
    
    @JsonProperty("relationship_type")
    public String getRelationshipType() {
        if (isPrimary != null && isPrimary) {
            return "PRIMARY";
        }
        return "SECONDARY";
    }
    
    @JsonProperty("description")
    public String getDescription() {
        return String.format("Post %d - Media %d (Order: %d, %s)", 
                           postId, mediaId, displayOrder, getRelationshipType());
    }
    
    // Helper methods for validation
    public boolean isValidRelationship() {
        return getIsValid();
    }
    
    public boolean isPrimaryMedia() {
        return isPrimary != null && isPrimary;
    }
    
    public boolean isSecondaryMedia() {
        return isPrimary != null && !isPrimary;
    }
    
    public boolean canSetAsPrimary() {
        return isValidRelationship();
    }
    
    // Static factory methods
    public static PostMediaDto create(Long postId, Long mediaId, Integer displayOrder, Boolean isPrimary) {
        PostMediaDto dto = new PostMediaDto();
        dto.setPostId(postId);
        dto.setMediaId(mediaId);
        dto.setDisplayOrder(displayOrder != null ? displayOrder : 1);
        dto.setIsPrimary(isPrimary != null ? isPrimary : false);
        return dto;
    }
    
    public static PostMediaDto createPrimary(Long postId, Long mediaId) {
        return create(postId, mediaId, 1, true);
    }
    
    public static PostMediaDto createSecondary(Long postId, Long mediaId, Integer displayOrder) {
        return create(postId, mediaId, displayOrder, false);
    }
    
    // Builder pattern methods
    public PostMediaDto withPost(PostDto post) {
        this.post = post;
        return this;
    }
    
    public PostMediaDto withMedia(MediaDto media) {
        this.media = media;
        return this;
    }
    
    public PostMediaDto withDisplayOrder(Integer displayOrder) {
        this.displayOrder = displayOrder;
        return this;
    }
    
    public PostMediaDto withPrimaryStatus(Boolean isPrimary) {
        this.isPrimary = isPrimary;
        return this;
    }
    
    // Validation groups for different operations
    public interface CreateValidation {}
    public interface UpdateValidation {}
    public interface ReorderValidation {}
    
    // Custom validation methods
    public boolean hasValidDisplayOrder() {
        return displayOrder != null && displayOrder > 0;
    }
    
    public boolean hasRequiredFields() {
        return postId != null && mediaId != null;
    }
    
    public boolean isComplete() {
        return hasRequiredFields() && hasValidDisplayOrder() && isPrimary != null;
    }
}
