package com.storycove.repository;

import com.storycove.entity.CollectionStory;
import com.storycove.entity.CollectionStoryId;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.UUID;

@Repository
public interface CollectionStoryRepository extends JpaRepository<CollectionStory, CollectionStoryId> {
    
    /**
     * Find all stories in a collection ordered by position
     */
    @Query("SELECT cs FROM CollectionStory cs " +
           "LEFT JOIN FETCH cs.story s " +
           "LEFT JOIN FETCH s.author " +
           "WHERE cs.collection.id = :collectionId " +
           "ORDER BY cs.position ASC")
    List<CollectionStory> findByCollectionIdOrderByPosition(@Param("collectionId") UUID collectionId);
    
    /**
     * Find story by collection and story ID
     */
    @Query("SELECT cs FROM CollectionStory cs " +
           "WHERE cs.collection.id = :collectionId AND cs.story.id = :storyId")
    CollectionStory findByCollectionIdAndStoryId(@Param("collectionId") UUID collectionId, @Param("storyId") UUID storyId);
    
    /**
     * Get next available position in collection
     */
    @Query("SELECT COALESCE(MAX(cs.position), 0) + 1000 FROM CollectionStory cs WHERE cs.collection.id = :collectionId")
    Integer getNextPosition(@Param("collectionId") UUID collectionId);
    
    /**
     * Remove all stories from a collection (used when deleting collection)
     */
    @Modifying
    @Query("DELETE FROM CollectionStory cs WHERE cs.collection.id = :collectionId")
    void deleteByCollectionId(@Param("collectionId") UUID collectionId);
    
    /**
     * Update positions for stories in a collection
     * Used for bulk position updates during reordering
     */
    @Modifying
    @Query("UPDATE CollectionStory cs SET cs.position = :position " +
           "WHERE cs.collection.id = :collectionId AND cs.story.id = :storyId")
    void updatePosition(@Param("collectionId") UUID collectionId, 
                       @Param("storyId") UUID storyId, 
                       @Param("position") Integer position);
    
    /**
     * Check if a story already exists in a collection
     */
    boolean existsByCollectionIdAndStoryId(UUID collectionId, UUID storyId);
    
    /**
     * Count stories in a collection
     */
    long countByCollectionId(UUID collectionId);
    
    /**
     * Find all collections that contain a specific story
     */
    @Query("SELECT cs FROM CollectionStory cs " +
           "LEFT JOIN FETCH cs.collection c " +
           "WHERE cs.story.id = :storyId " +
           "ORDER BY c.name ASC")
    List<CollectionStory> findByStoryId(@Param("storyId") UUID storyId);
    
    /**
     * Find previous and next stories for reading navigation
     */
    @Query("SELECT cs FROM CollectionStory cs " +
           "WHERE cs.collection.id = :collectionId " +
           "AND cs.position < (SELECT current.position FROM CollectionStory current " +
           "                   WHERE current.collection.id = :collectionId AND current.story.id = :currentStoryId) " +
           "ORDER BY cs.position DESC")
    List<CollectionStory> findPreviousStory(@Param("collectionId") UUID collectionId, @Param("currentStoryId") UUID currentStoryId);
    
    @Query("SELECT cs FROM CollectionStory cs " +
           "WHERE cs.collection.id = :collectionId " +
           "AND cs.position > (SELECT current.position FROM CollectionStory current " +
           "                   WHERE current.collection.id = :collectionId AND current.story.id = :currentStoryId) " +
           "ORDER BY cs.position ASC")
    List<CollectionStory> findNextStory(@Param("collectionId") UUID collectionId, @Param("currentStoryId") UUID currentStoryId);
}