package com.social.media.service;

import com.social.media.dto.PostMediaDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Service interface for PostMedia operations
 */
public interface PostMediaService {
    
    // ==========================================
    // BASIC CRUD OPERATIONS
    // ==========================================
    
    /**
     * Create a new post-media relationship
     */
    PostMediaDto createPostMedia(PostMediaDto postMediaDto);
    
    /**
     * Create multiple post-media relationships
     */
    List<PostMediaDto> createPostMediaBatch(List<PostMediaDto> postMediaDtos);
    
    /**
     * Get post-media relationship by ID
     */
    Optional<PostMediaDto> getPostMediaById(Long id);
    
    /**
     * Update post-media relationship
     */
    PostMediaDto updatePostMedia(Long id, PostMediaDto postMediaDto);
    
    /**
     * Delete post-media relationship
     */
    void deletePostMedia(Long id);
    
    /**
     * Get all post-media relationships with pagination
     */
    Page<PostMediaDto> getAllPostMedia(Pageable pageable);
    
    // ==========================================
    // POST-SPECIFIC OPERATIONS
    // ==========================================
    
    /**
     * Get all media for a specific post ordered by display order
     */
    List<PostMediaDto> getMediaForPost(Long postId);
    
    /**
     * Get all media for a specific post with pagination
     */
    Page<PostMediaDto> getMediaForPost(Long postId, Pageable pageable);
    
    /**
     * Get primary media for a specific post
     */
    Optional<PostMediaDto> getPrimaryMediaForPost(Long postId);
    
    /**
     * Get secondary media for a specific post
     */
    List<PostMediaDto> getSecondaryMediaForPost(Long postId);
    
    /**
     * Add media to post
     */
    PostMediaDto addMediaToPost(Long postId, Long mediaId, Integer displayOrder, Boolean isPrimary);
    
    /**
     * Add multiple media to post
     */
    List<PostMediaDto> addMultipleMediaToPost(Long postId, List<Long> mediaIds);
    
    /**
     * Remove media from post
     */
    void removeMediaFromPost(Long postId, Long mediaId);
    
    /**
     * Remove all media from post
     */
    void removeAllMediaFromPost(Long postId);
    
    /**
     * Count media files for a post
     */
    Long countMediaForPost(Long postId);
    
    /**
     * Check if post has media
     */
    boolean postHasMedia(Long postId);
    
    /**
     * Check if post has primary media
     */
    boolean postHasPrimaryMedia(Long postId);
    
    // ==========================================
    // MEDIA-SPECIFIC OPERATIONS
    // ==========================================
    
    /**
     * Get all posts using a specific media
     */
    List<PostMediaDto> getPostsUsingMedia(Long mediaId);
    
    /**
     * Get posts where media is used as primary
     */
    List<PostMediaDto> getPostsWherePrimary(Long mediaId);
    
    /**
     * Count posts using a specific media
     */
    Long countPostsUsingMedia(Long mediaId);
    
    /**
     * Check if media is used in any post
     */
    boolean mediaIsUsed(Long mediaId);
    
    /**
     * Check if media is used as primary in any post
     */
    boolean mediaIsUsedAsPrimary(Long mediaId);
    
    /**
     * Remove media from all posts
     */
    void removeMediaFromAllPosts(Long mediaId);
    
    // ==========================================
    // PRIMARY MEDIA MANAGEMENT
    // ==========================================
    
    /**
     * Set media as primary for a post (removes primary status from others)
     */
    PostMediaDto setPrimaryMedia(Long postId, Long mediaId);
    
    /**
     * Remove primary status from all media in a post
     */
    void removePrimaryStatusFromPost(Long postId);
    
    /**
     * Auto-assign primary media if none exists (uses first by display order)
     */
    Optional<PostMediaDto> autoAssignPrimaryMedia(Long postId);
    
    /**
     * Validate primary media constraints for a post
     */
    boolean validatePrimaryMediaConstraints(Long postId);
    
    // ==========================================
    // DISPLAY ORDER MANAGEMENT
    // ==========================================
    
    /**
     * Reorder media for a post
     */
    List<PostMediaDto> reorderPostMedia(Long postId, List<Long> mediaIdsInOrder);
    
    /**
     * Move media up in display order
     */
    PostMediaDto moveMediaUp(Long postId, Long mediaId);
    
    /**
     * Move media down in display order
     */
    PostMediaDto moveMediaDown(Long postId, Long mediaId);
    
    /**
     * Move media to specific position
     */
    PostMediaDto moveMediaToPosition(Long postId, Long mediaId, Integer newPosition);
    
    /**
     * Move media to first position
     */
    PostMediaDto moveMediaToFirst(Long postId, Long mediaId);
    
    /**
     * Move media to last position
     */
    PostMediaDto moveMediaToLast(Long postId, Long mediaId);
    
    /**
     * Normalize display orders for a post (1, 2, 3, ...)
     */
    List<PostMediaDto> normalizeDisplayOrders(Long postId);
    
    /**
     * Get next available display order for a post
     */
    Integer getNextDisplayOrder(Long postId);
    
    // ==========================================
    // RELATIONSHIP VALIDATION
    // ==========================================
    
    /**
     * Check if post-media relationship exists
     */
    boolean relationshipExists(Long postId, Long mediaId);
    
    /**
     * Get specific post-media relationship
     */
    Optional<PostMediaDto> getRelationship(Long postId, Long mediaId);
    
    /**
     * Validate post-media relationship
     */
    boolean validateRelationship(PostMediaDto postMediaDto);
    
    /**
     * Check for duplicate relationships
     */
    List<PostMediaDto> findDuplicateRelationships();
    
    /**
     * Find orphaned relationships
     */
    List<PostMediaDto> findOrphanedRelationships();
    
    // ==========================================
    // BULK OPERATIONS
    // ==========================================
    
    /**
     * Copy media from one post to another
     */
    List<PostMediaDto> copyMediaFromPost(Long sourcePostId, Long targetPostId);
    
    /**
     * Move media from one post to another
     */
    List<PostMediaDto> moveMediaFromPost(Long sourcePostId, Long targetPostId);
    
    /**
     * Duplicate post media structure
     */
    List<PostMediaDto> duplicatePostMediaStructure(Long sourcePostId, Long targetPostId);
    
    /**
     * Merge media from multiple posts
     */
    List<PostMediaDto> mergeMediaFromPosts(List<Long> sourcePostIds, Long targetPostId);
    
    /**
     * Update display orders in batch
     */
    List<PostMediaDto> updateDisplayOrdersBatch(List<PostMediaDto> postMediaDtos);
    
    // ==========================================
    // SEARCH AND FILTERING
    // ==========================================
    
    /**
     * Search post-media relationships by criteria
     */
    Page<PostMediaDto> searchPostMedia(
        Long postId, 
        Long mediaId, 
        Boolean isPrimary, 
        Integer minDisplayOrder, 
        Integer maxDisplayOrder,
        Pageable pageable
    );
    
    /**
     * Find posts with multiple media
     */
    List<Long> getPostsWithMultipleMedia();
    
    /**
     * Find posts without primary media
     */
    List<Long> getPostsWithoutPrimaryMedia();
    
    /**
     * Find media used in multiple posts
     */
    List<Long> getMediaUsedInMultiplePosts();
    
    /**
     * Find posts with specific media count
     */
    List<Long> getPostsWithMediaCount(Long count);
    
    // ==========================================
    // STATISTICS AND ANALYTICS
    // ==========================================
    
    /**
     * Get media usage statistics
     */
    Map<String, Object> getMediaUsageStatistics();
    
    /**
     * Get posts with most media files
     */
    List<Map<String, Object>> getPostsWithMostMedia(int limit);
    
    /**
     * Get most used media files
     */
    List<Map<String, Object>> getMostUsedMedia(int limit);
    
    /**
     * Get media distribution by display order
     */
    Map<Integer, Long> getMediaDistributionByDisplayOrder();
    
    /**
     * Get media usage by primary vs secondary
     */
    Map<Long, Map<String, Long>> getMediaUsageByPrimaryStatus();
    
    /**
     * Get average media count per post
     */
    Double getAverageMediaCountPerPost();
    
    /**
     * Get primary media percentage
     */
    Double getPrimaryMediaPercentage();
    
    // ==========================================
    // DATE-BASED OPERATIONS
    // ==========================================
    
    /**
     * Get relationships created in date range
     */
    List<PostMediaDto> getRelationshipsInDateRange(LocalDateTime startDate, LocalDateTime endDate);
    
    /**
     * Get recent relationships
     */
    List<PostMediaDto> getRecentRelationships(int hours, int limit);
    
    /**
     * Count relationships created today
     */
    Long countTodayRelationships();
    
    /**
     * Get relationship creation timeline
     */
    Map<String, Long> getRelationshipCreationTimeline(int days);
    
    // ==========================================
    // MAINTENANCE AND HEALTH
    // ==========================================
    
    /**
     * Validate all relationships integrity
     */
    Map<String, Object> validateAllRelationshipsIntegrity();
    
    /**
     * Fix display order gaps
     */
    int fixDisplayOrderGaps();
    
    /**
     * Clean up invalid relationships
     */
    int cleanupInvalidRelationships();
    
    /**
     * Get health check information
     */
    Map<String, Object> getHealthCheckInfo();
    
    /**
     * Rebuild all display orders
     */
    int rebuildAllDisplayOrders();
    
    /**
     * Find and fix duplicate display orders
     */
    Map<Long, List<Integer>> findAndFixDuplicateDisplayOrders();
    
    // ==========================================
    // IMPORT/EXPORT OPERATIONS
    // ==========================================
    
    /**
     * Export post-media relationships
     */
    List<PostMediaDto> exportPostMediaRelationships(Long postId);
    
    /**
     * Import post-media relationships
     */
    List<PostMediaDto> importPostMediaRelationships(Long postId, List<PostMediaDto> relationships);
    
    /**
     * Export all relationships for backup
     */
    List<PostMediaDto> exportAllRelationships();
    
    /**
     * Generate relationship summary
     */
    Map<String, Object> generateRelationshipSummary(Long postId);
}
