package com.social.media.service;

import com.social.media.domain.entity.Media;
import com.social.media.domain.entity.Media.MediaFormat;
import com.social.media.domain.entity.Media.MediaValidationStatus;
import com.social.media.dto.MediaDto;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public interface MediaService {
    
    // Basic CRUD operations
    MediaDto save(MediaDto mediaDto);
    MediaDto update(Long id, MediaDto mediaDto);
    void delete(Long id);
    void softDelete(Long id);
    void restore(Long id);
    Optional<MediaDto> findById(Long id);
    List<MediaDto> findAll();
    Page<MediaDto> findAll(Pageable pageable);
    
    // Find by unique identifiers
    Optional<MediaDto> findByMediaCode(String mediaCode);
    Optional<MediaDto> findByStoredFilename(String storedFilename);
    Optional<MediaDto> findByFileChecksum(String fileChecksum);
    
    // Company-based operations
    List<MediaDto> findByCompanyId(Long companyId);
    Page<MediaDto> findByCompanyId(Long companyId, Pageable pageable);
    List<MediaDto> findActiveByCompanyId(Long companyId);
    Page<MediaDto> findActiveByCompanyId(Long companyId, Pageable pageable);
    
    // User-based operations
    List<MediaDto> findByUploadedBy(Long uploadedBy);
    Page<MediaDto> findByUploadedBy(Long uploadedBy, Pageable pageable);
    List<MediaDto> findActiveByUploadedBy(Long uploadedBy);
    Page<MediaDto> findActiveByUploadedBy(Long uploadedBy, Pageable pageable);
    
    // Format-based operations
    List<MediaDto> findByFormat(MediaFormat format);
    Page<MediaDto> findByFormat(MediaFormat format, Pageable pageable);
    List<MediaDto> findByCompanyIdAndFormat(Long companyId, MediaFormat format);
    Page<MediaDto> findByCompanyIdAndFormat(Long companyId, MediaFormat format, Pageable pageable);
    
    // Validation status operations
    List<MediaDto> findByValidationStatus(MediaValidationStatus validationStatus);
    Page<MediaDto> findByValidationStatus(MediaValidationStatus validationStatus, Pageable pageable);
    List<MediaDto> findByCompanyIdAndValidationStatus(Long companyId, MediaValidationStatus status);
    Page<MediaDto> findByCompanyIdAndValidationStatus(Long companyId, MediaValidationStatus status, Pageable pageable);
    
    // Public/Private operations
    List<MediaDto> findByIsPublic(Boolean isPublic);
    Page<MediaDto> findByIsPublic(Boolean isPublic, Pageable pageable);
    List<MediaDto> findByCompanyIdAndIsPublic(Long companyId, Boolean isPublic);
    Page<MediaDto> findByCompanyIdAndIsPublic(Long companyId, Boolean isPublic, Pageable pageable);
    
    // Date range operations
    List<MediaDto> findByUploadedAtBetween(LocalDateTime startDate, LocalDateTime endDate);
    Page<MediaDto> findByUploadedAtBetween(LocalDateTime startDate, LocalDateTime endDate, Pageable pageable);
    List<MediaDto> findByCompanyIdAndUploadedAtBetween(Long companyId, LocalDateTime startDate, LocalDateTime endDate);
    Page<MediaDto> findByCompanyIdAndUploadedAtBetween(Long companyId, LocalDateTime startDate, LocalDateTime endDate, Pageable pageable);
    
    // File size operations
    List<MediaDto> findByFileSizeBetween(Long minSize, Long maxSize);
    Page<MediaDto> findByFileSizeBetween(Long minSize, Long maxSize, Pageable pageable);
    List<MediaDto> findLargeFilesByCompanyId(Long companyId, Long minSize);
    
    // MIME type operations
    List<MediaDto> findByMimeType(String mimeType);
    List<MediaDto> findByMimeTypeContaining(String mimeTypePattern);
    
    // Search operations
    List<MediaDto> searchByCompanyId(Long companyId, String searchTerm);
    Page<MediaDto> searchByCompanyId(Long companyId, String searchTerm, Pageable pageable);
    Page<MediaDto> findWithFilters(Long companyId, MediaFormat format, MediaValidationStatus validationStatus, 
                                  Boolean isPublic, Long uploadedBy, Pageable pageable);
    
    // Type-specific operations
    List<MediaDto> findImagesByCompanyId(Long companyId);
    Page<MediaDto> findImagesByCompanyId(Long companyId, Pageable pageable);
    List<MediaDto> findVideosByCompanyId(Long companyId);
    Page<MediaDto> findVideosByCompanyId(Long companyId, Pageable pageable);
    List<MediaDto> findAudiosByCompanyId(Long companyId);
    Page<MediaDto> findAudiosByCompanyId(Long companyId, Pageable pageable);
    List<MediaDto> findDocumentsByCompanyId(Long companyId);
    Page<MediaDto> findDocumentsByCompanyId(Long companyId, Pageable pageable);
    
    // File upload operations
    MediaDto uploadFile(MultipartFile file, Long companyId, Long uploadedBy, String description, String altText, Boolean isPublic);
    MediaDto uploadFileWithMetadata(MultipartFile file, Long companyId, Long uploadedBy, String description, String altText, Boolean isPublic, Map<String, Object> metadata);
    List<MediaDto> uploadMultipleFiles(MultipartFile[] files, Long companyId, Long uploadedBy, Boolean isPublic);
    
    // File processing operations
    MediaDto processImageFile(MultipartFile file, Long companyId, Long uploadedBy, String description, String altText, Boolean isPublic);
    MediaDto processVideoFile(MultipartFile file, Long companyId, Long uploadedBy, String description, String altText, Boolean isPublic);
    MediaDto processAudioFile(MultipartFile file, Long companyId, Long uploadedBy, String description, String altText, Boolean isPublic);
    MediaDto processDocumentFile(MultipartFile file, Long companyId, Long uploadedBy, String description, String altText, Boolean isPublic);
    
    // Validation operations
    void approveMedia(Long id, String notes);
    void rejectMedia(Long id, String notes);
    void flagMedia(Long id, String notes);
    void requestReview(Long id);
    List<MediaDto> findPendingValidation(Long companyId);
    Page<MediaDto> findPendingValidation(Long companyId, Pageable pageable);
    List<MediaDto> findPendingValidationOlderThan(LocalDateTime cutoffDate);
    
    // Storage operations
    byte[] getFileContent(Long id);
    byte[] getFileContent(String storedFilename);
    String getFileUrl(Long id);
    String getFileUrl(String storedFilename);
    String getThumbnailUrl(Long id);
    String getPreviewUrl(Long id);
    boolean fileExists(Long id);
    boolean fileExists(String storedFilename);
    
    // Duplicate detection
    List<MediaDto> findDuplicatesByChecksum(Long companyId, String checksum);
    List<MediaDto> findPotentialDuplicates(Long companyId, String filename, Long fileSize);
    boolean isDuplicate(Long companyId, String checksum);
    boolean isDuplicate(Long companyId, String filename, Long fileSize);
    
    // Maintenance operations
    List<MediaDto> findDeleted();
    Page<MediaDto> findDeleted(Pageable pageable);
    List<MediaDto> findDeletedBefore(LocalDateTime cutoffDate);
    void permanentDelete(Long id);
    void cleanupDeletedFiles(LocalDateTime cutoffDate);
    void validateFileIntegrity(Long companyId);
    List<String> findOrphanedFiles(Long companyId);
    void cleanupOrphanedFiles(Long companyId);
    
    // Statistical operations
    Long countActiveByCompanyId(Long companyId);
    Long countByCompanyIdAndFormat(Long companyId, MediaFormat format);
    Long countByCompanyIdAndValidationStatus(Long companyId, MediaValidationStatus status);
    Long getTotalFileSizeByCompanyId(Long companyId);
    Double getAverageFileSizeByCompanyId(Long companyId);
    Map<String, Long> getFormatStatisticsByCompanyId(Long companyId);
    Map<String, Long> getTopUploadersByCompanyId(Long companyId);
    Map<String, Object> getCompanyMediaStatistics(Long companyId);
    Map<String, Object> getGlobalMediaStatistics();
    
    // Storage provider operations
    List<MediaDto> findByStorageProvider(String storageProvider);
    List<MediaDto> findActiveByStorageProvider(String storageProvider);
    void migrateToStorageProvider(Long companyId, String newProvider);
    void migrateFileToStorageProvider(Long id, String newProvider);
    
    // Recent operations
    List<MediaDto> findRecentUploads(Long companyId, LocalDateTime since);
    Page<MediaDto> findRecentUploads(Long companyId, LocalDateTime since, Pageable pageable);
    List<MediaDto> findRecentUploadsByUser(Long uploadedBy, LocalDateTime since);
    
    // Batch operations
    void approveMultiple(List<Long> ids, String notes);
    void rejectMultiple(List<Long> ids, String notes);
    void deleteMultiple(List<Long> ids);
    void softDeleteMultiple(List<Long> ids);
    void restoreMultiple(List<Long> ids);
    void updateVisibilityMultiple(List<Long> ids, Boolean isPublic);
    void moveToCompany(List<Long> ids, Long newCompanyId);
    
    // Media processing operations
    MediaDto generateThumbnail(Long id);
    MediaDto generatePreview(Long id);
    MediaDto resizeImage(Long id, Integer width, Integer height);
    MediaDto convertFormat(Long id, MediaFormat newFormat);
    MediaDto compressFile(Long id);
    MediaDto extractMetadata(Long id);
    void refreshMetadata(Long id);
    void refreshAllMetadata(Long companyId);
    
    // Security operations
    boolean hasAccess(Long id, Long userId);
    boolean hasAccess(Long id, Long userId, Long companyId);
    boolean canEdit(Long id, Long userId);
    boolean canDelete(Long id, Long userId);
    boolean canApprove(Long id, Long userId);
    void setPermissions(Long id, Map<String, Object> permissions);
    Map<String, Object> getPermissions(Long id);
    
    // Import/Export operations
    List<MediaDto> importFromUrl(List<String> urls, Long companyId, Long uploadedBy);
    MediaDto importFromUrl(String url, Long companyId, Long uploadedBy, String description);
    void exportToCloud(Long companyId, String cloudProvider, Map<String, Object> config);
    void exportSelection(List<Long> ids, String format, String destination);
    
    // Validation operations
    boolean isValidFormat(String filename);
    boolean isValidSize(Long fileSize);
    boolean isValidMimeType(String mimeType);
    MediaFormat detectFormat(String filename, String mimeType);
    String generateUniqueFilename(String originalFilename, Long companyId);
    String calculateChecksum(byte[] fileContent);
    
    // Existence checks
    boolean existsByMediaCode(String mediaCode);
    boolean existsByStoredFilename(String storedFilename);
    boolean existsByFileChecksum(String fileChecksum);
    boolean existsByCompanyIdAndStoredFilename(Long companyId, String filename);
}
