🏡 index : ironmagma/quintodrome.git

package migrations

import (
	"context"
	"database/sql"

	"github.com/pressly/goose/v3"
)

func init() {
	goose.AddMigrationContext(upAddMultiLibrarySupport, downAddMultiLibrarySupport)
}

func upAddMultiLibrarySupport(ctx context.Context, tx *sql.Tx) error {
	_, err := tx.ExecContext(ctx, `
	-- Create user_library association table
		CREATE TABLE user_library (
			user_id VARCHAR(255) NOT NULL,
			library_id INTEGER NOT NULL,
			PRIMARY KEY (user_id, library_id),
			FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE,
			FOREIGN KEY (library_id) REFERENCES library(id) ON DELETE CASCADE
		);
	-- Create indexes for performance
		CREATE INDEX idx_user_library_user_id ON user_library(user_id);
		CREATE INDEX idx_user_library_library_id ON user_library(library_id);

	-- Populate with existing users having access to library ID 1 (existing setup)
	-- Admin users get access to all libraries, regular users get access to library 1
		INSERT INTO user_library (user_id, library_id)
		SELECT u.id, 1
		FROM user u;

	-- Add total_duration column to library table
		ALTER TABLE library ADD COLUMN total_duration real DEFAULT 0;
		UPDATE library SET total_duration = (
			SELECT IFNULL(SUM(duration),0) from album where album.library_id = library.id and missing = 0
		);

	-- Add default_new_users column to library table
		ALTER TABLE library ADD COLUMN default_new_users boolean DEFAULT false;
		-- Set library ID 1 (default library) as default for new users
		UPDATE library SET default_new_users = true WHERE id = 1;

	-- Add stats column to library_artist junction table for per-library artist statistics
		ALTER TABLE library_artist ADD COLUMN stats text DEFAULT '{}';
		
	-- Migrate existing global artist stats to per-library format in library_artist table
	-- For each library_artist association, copy the artist's global stats
		UPDATE library_artist 
		SET stats = (
			SELECT COALESCE(artist.stats, '{}')
			FROM artist 
			WHERE artist.id = library_artist.artist_id
		);

	-- Remove stats column from artist table to eliminate duplication
	-- Stats are now stored per-library in library_artist table
		ALTER TABLE artist DROP COLUMN stats;

	-- Create library_tag table for per-library tag statistics
		CREATE TABLE library_tag (
			tag_id VARCHAR NOT NULL,
			library_id INTEGER NOT NULL,
			album_count INTEGER DEFAULT 0 NOT NULL,
			media_file_count INTEGER DEFAULT 0 NOT NULL,
			PRIMARY KEY (tag_id, library_id),
			FOREIGN KEY (tag_id) REFERENCES tag(id) ON DELETE CASCADE,
			FOREIGN KEY (library_id) REFERENCES library(id) ON DELETE CASCADE
		);

	-- Create indexes for optimal query performance
		CREATE INDEX idx_library_tag_tag_id ON library_tag(tag_id);
		CREATE INDEX idx_library_tag_library_id ON library_tag(library_id);

	-- Migrate existing tag stats to per-library format in library_tag table
	-- For existing installations, copy current global stats to library ID 1 (default library)
		INSERT INTO library_tag (tag_id, library_id, album_count, media_file_count)
		SELECT t.id, 1, t.album_count, t.media_file_count
		FROM tag t
		WHERE EXISTS (SELECT 1 FROM library WHERE id = 1);

	-- Remove global stats from tag table as they are now per-library
		ALTER TABLE tag DROP COLUMN album_count;
		ALTER TABLE tag DROP COLUMN media_file_count;
	`)

	return err
}

func downAddMultiLibrarySupport(ctx context.Context, tx *sql.Tx) error {
	_, err := tx.ExecContext(ctx, `
		-- Restore stats column to artist table before removing from library_artist
		ALTER TABLE artist ADD COLUMN stats text DEFAULT '{}';
		
		-- Restore global stats by aggregating from library_artist (simplified approach)
		-- In a real rollback scenario, this might need more sophisticated logic
		UPDATE artist 
		SET stats = (
			SELECT COALESCE(la.stats, '{}')
			FROM library_artist la 
			WHERE la.artist_id = artist.id 
			LIMIT 1
		);
		
		ALTER TABLE library_artist DROP COLUMN IF EXISTS stats;
		DROP INDEX IF EXISTS idx_user_library_library_id;
		DROP INDEX IF EXISTS idx_user_library_user_id;
		DROP TABLE IF EXISTS user_library;
		ALTER TABLE library DROP COLUMN IF EXISTS total_duration;
		ALTER TABLE library DROP COLUMN IF EXISTS default_new_users;
		
		-- Drop library_tag table and its indexes
		DROP INDEX IF EXISTS idx_library_tag_library_id;
		DROP INDEX IF EXISTS idx_library_tag_tag_id;
		DROP TABLE IF EXISTS library_tag;
	`)
	return err
}