-- ================================================
-- Jellyfin PostgreSQL Migration
-- Migration: 20260227000000_AddSupplementaryIndexes
-- Purpose: Add performance indexes for improved query performance
-- ================================================
-- 
-- INSTRUCTIONS:
-- 1. Connect to your Jellyfin PostgreSQL database
-- 2. Run this script using psql, pgAdmin, or any PostgreSQL client
-- 3. Verify indexes are created (see verification query at end)
--
-- ================================================

BEGIN;

-- Check if migration was already applied
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM library."__EFMigrationsHistory" 
        WHERE "MigrationId" = '20260227000000_AddSupplementaryIndexes'
    ) THEN
        RAISE NOTICE 'Migration 20260227000000_AddSupplementaryIndexes already applied. Skipping...';
    ELSE
        RAISE NOTICE 'Applying migration 20260227000000_AddSupplementaryIndexes...';
    END IF;
END $$;

COMMIT;

-- ================================================
-- Create Indexes (CONCURRENTLY - safe for production)
-- ================================================

-- 1. Composite index for filtered library browsing (type + virtual + parent)
-- Use case: Browse items by type in a specific library, excluding virtual items
-- Improves queries like: "SELECT * FROM BaseItems WHERE Type='Movie' AND IsVirtualItem=false AND TopParentId='xyz'"
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_type_isvirtualitem_topparentid
ON library."BaseItems" ("Type", "IsVirtualItem", "TopParentId")
WHERE "IsVirtualItem" = false;

-- 2. Index for folder hierarchy queries
-- Use case: Navigate folder structures efficiently
-- Improves queries like: "SELECT * FROM BaseItems WHERE TopParentId='xyz' AND IsFolder=true"
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_topparentid_isfolder
ON library."BaseItems" ("TopParentId", "IsFolder", "IsVirtualItem")
WHERE "TopParentId" IS NOT NULL;

-- 3. Index for recently added content with filters
-- Use case: "Recently Added" view across all libraries
-- Improves queries like: "SELECT * FROM BaseItems WHERE IsVirtualItem=false ORDER BY DateCreated DESC"
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_datecreated_filtered
ON library."BaseItems" ("DateCreated" DESC, "Type", "IsVirtualItem")
WHERE "DateCreated" IS NOT NULL AND "IsVirtualItem" = false;

-- 4. Index for reverse lookup (find items by genre/tag)
-- Use case: "Show all items with genre 'Action'"
-- Improves queries like: "SELECT ItemId FROM ItemValuesMap WHERE ItemValueId='action-genre-id'"
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvaluesmap_itemvalueid_itemid
ON library."ItemValuesMap" ("ItemValueId", "ItemId");

-- 5. Index for user-specific activity queries
-- Use case: "Show activity for user X"
-- Improves queries like: "SELECT * FROM ActivityLogs WHERE UserId='user-id' ORDER BY DateCreated DESC"
-- Note: This will fail gracefully if the activitylog.ActivityLogs table doesn't exist
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activitylogs_userid_datecreated
ON activitylog."ActivityLogs" ("UserId", "DateCreated" DESC)
WHERE "UserId" IS NOT NULL;

-- 6. Index for episode deduplication by PresentationUniqueKey
-- Use case: Group and deduplicate episodes (used in GetItems queries)
-- Improves queries like: "SELECT * FROM BaseItems WHERE Type='Episode' AND PresentationUniqueKey='xyz'"
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_presentationuniquekey_episodes
ON library."BaseItems" ("PresentationUniqueKey", "TopParentId", "IsVirtualItem")
WHERE "Type" = 'MediaBrowser.Controller.Entities.TV.Episode' AND "PresentationUniqueKey" IS NOT NULL;

-- ================================================
-- Update migration history
-- ================================================

BEGIN;

INSERT INTO library."__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20260227000000_AddSupplementaryIndexes', '11.0.0')
ON CONFLICT ("MigrationId") DO NOTHING;

COMMIT;

-- ================================================
-- Verification Query
-- ================================================
-- Run this to verify all indexes were created successfully:

SELECT 
    schemaname AS "Schema",
    tablename AS "Table",
    indexname AS "Index Name",
    indexdef AS "Definition"
FROM pg_indexes
WHERE indexname IN (
    'idx_baseitems_type_isvirtualitem_topparentid',
    'idx_baseitems_topparentid_isfolder',
    'idx_baseitems_datecreated_filtered',
    'idx_itemvaluesmap_itemvalueid_itemid',
    'idx_activitylogs_userid_datecreated',
    'idx_baseitems_presentationuniquekey_episodes'
)
ORDER BY schemaname, tablename, indexname;

-- Expected: 6 rows (or 5 if ActivityLogs table doesn't exist)
