/**
 * Migration: 012 - Fix TF-IDF Dimension Trigger
 * Description: Fix memory_embedding_vec_insert and memory_embedding_vec_update triggers
 *              to use dimensions = 512 for TF-IDF instead of 384
 * Version: 12.0
 * Date: 2025-01-11
 *
 * 왜 필요한가?
 * - TF-IDF 임베딩은 512차원을 생성하지만, 트리거에서 dimensions = 384로 검사하여
 *   memory_item_vec_tfidf 테이블(512차원)에 삽입되지 않음
 * - 결과적으로 검색 시 차원 불일치 오류 발생
 * - 이 마이그레이션은 트리거를 재생성하여 TF-IDF 차원 조건을 384에서 512로 수정
 */
import { logger } from '../../../../../shared/utils/logger.js';
/**
 * Fix TF-IDF Dimension Trigger Migration
 *
 * This migration:
 * 1. Drops existing memory_embedding_vec_insert and memory_embedding_vec_update triggers
 * 2. Recreates them with correct dimension condition (512 for TF-IDF)
 */
export class FixTfidfDimensionTriggerMigration {
    version = '12.0';
    name = 'fix-tfidf-dimension-trigger';
    description = 'Fix memory_embedding_vec_insert and memory_embedding_vec_update triggers to use dimensions = 512 for TF-IDF instead of 384';
    /**
     * Check if trigger exists
     * @param db 데이터베이스 인스턴스
     * @param triggerName 확인할 트리거명
     * @returns 트리거 존재 여부
     */
    triggerExists(db, triggerName) {
        const result = db
            .prepare(`
        SELECT name FROM sqlite_master 
        WHERE type='trigger' AND name=?
      `)
            .get(triggerName);
        return !!result;
    }
    /**
     * Check if table exists
     * @param db 데이터베이스 인스턴스
     * @param tableName 확인할 테이블명
     * @returns 테이블 존재 여부
     */
    tableExists(db, tableName) {
        const result = db
            .prepare(`
        SELECT name FROM sqlite_master 
        WHERE type='table' AND name=?
      `)
            .get(tableName);
        return !!result;
    }
    /**
     * Validate before migration
     */
    async validateBefore(db) {
        // Check if memory_embedding table exists (required for triggers)
        if (!this.tableExists(db, 'memory_embedding')) {
            throw new Error('memory_embedding table does not exist. Cannot proceed with migration.');
        }
        // Check if memory_item_vec_tfidf table exists (required for triggers)
        // Note: This table may not exist in test environments. If it doesn't exist,
        // the migration will still proceed but the TF-IDF trigger operations will be skipped.
        // The table should be created by a previous migration in production environments.
        if (!this.tableExists(db, 'memory_item_vec_tfidf')) {
            // Log warning but don't throw error - allow migration to proceed
            // The up() method will handle missing tables gracefully
            logger.warn('⚠️  memory_item_vec_tfidf table does not exist. TF-IDF trigger operations will be skipped.');
        }
        // Check if migration has already been applied
        if (this.tableExists(db, 'memento_schema_version')) {
            const version = db.prepare(`
        SELECT version FROM memento_schema_version WHERE version = ?
      `).get('12.0');
            if (version) {
                throw new Error('Migration 012 has already been applied. Current schema version: 12.0');
            }
        }
        // Note: Dependency validation is handled by MigrationRunner automatically
        // MigrationRunner checks dependencies based on the version array in detectPendingMigrations
    }
    /**
     * Execute migration (Up)
     */
    async up(db) {
        // Check which vec tables exist to build appropriate trigger
        const hasTfidfTable = this.tableExists(db, 'memory_item_vec_tfidf');
        const hasMinilmTable = this.tableExists(db, 'memory_item_vec_minilm');
        const hasOpenaiTable = this.tableExists(db, 'memory_item_vec_openai');
        const hasGeminiTable = this.tableExists(db, 'memory_item_vec_gemini');
        const hasVecTable = this.tableExists(db, 'memory_item_vec');
        // Check if at least one table exists
        const hasAnyTable = hasVecTable || hasTfidfTable || hasMinilmTable || hasOpenaiTable || hasGeminiTable;
        // Drop existing triggers
        db.exec('DROP TRIGGER IF EXISTS memory_embedding_vec_insert');
        db.exec('DROP TRIGGER IF EXISTS memory_embedding_vec_update');
        // Only create triggers if at least one table exists
        if (!hasAnyTable) {
            logger.warn('⚠️  No vec tables exist. Skipping trigger creation.');
            return;
        }
        // Build trigger SQL conditionally based on which tables exist
        const insertStatements = [];
        const updateDeleteStatements = [];
        const updateInsertStatements = [];
        if (hasVecTable) {
            insertStatements.push(`
        INSERT INTO memory_item_vec(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.dimensions = 384;
      `);
            updateDeleteStatements.push(`DELETE FROM memory_item_vec WHERE rowid = NEW.id;`);
            updateInsertStatements.push(`
        INSERT INTO memory_item_vec(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.dimensions = 384;
      `);
        }
        if (hasTfidfTable) {
            insertStatements.push(`
        INSERT INTO memory_item_vec_tfidf(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'tfidf' AND NEW.dimensions = 512 AND NEW.projection_type = 'native';
      `);
            updateDeleteStatements.push(`DELETE FROM memory_item_vec_tfidf WHERE rowid = NEW.id;`);
            updateInsertStatements.push(`
        INSERT INTO memory_item_vec_tfidf(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'tfidf' AND NEW.dimensions = 512 AND NEW.projection_type = 'native';
      `);
        }
        if (hasMinilmTable) {
            insertStatements.push(`
        INSERT INTO memory_item_vec_minilm(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'minilm' AND NEW.dimensions = 384 AND NEW.projection_type = 'native';
      `);
            updateDeleteStatements.push(`DELETE FROM memory_item_vec_minilm WHERE rowid = NEW.id;`);
            updateInsertStatements.push(`
        INSERT INTO memory_item_vec_minilm(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'minilm' AND NEW.dimensions = 384 AND NEW.projection_type = 'native';
      `);
        }
        if (hasOpenaiTable) {
            insertStatements.push(`
        INSERT INTO memory_item_vec_openai(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'openai' AND NEW.dimensions = 1536 AND NEW.projection_type = 'native';
      `);
            updateDeleteStatements.push(`DELETE FROM memory_item_vec_openai WHERE rowid = NEW.id;`);
            updateInsertStatements.push(`
        INSERT INTO memory_item_vec_openai(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'openai' AND NEW.dimensions = 1536 AND NEW.projection_type = 'native';
      `);
        }
        if (hasGeminiTable) {
            insertStatements.push(`
        INSERT INTO memory_item_vec_gemini(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'gemini' AND NEW.dimensions = 768 AND NEW.projection_type = 'native';
      `);
            updateDeleteStatements.push(`DELETE FROM memory_item_vec_gemini WHERE rowid = NEW.id;`);
            updateInsertStatements.push(`
        INSERT INTO memory_item_vec_gemini(rowid, embedding) 
        SELECT NEW.id, json_extract(NEW.embedding, '$')
        WHERE NEW.embedding_provider = 'gemini' AND NEW.dimensions = 768 AND NEW.projection_type = 'native';
      `);
        }
        // Build insert trigger SQL
        const insertTriggerSQL = `
      CREATE TRIGGER IF NOT EXISTS memory_embedding_vec_insert AFTER INSERT ON memory_embedding BEGIN
        ${insertStatements.join('')}
      END
    `;
        // Build update trigger SQL
        const updateTriggerSQL = `
      CREATE TRIGGER IF NOT EXISTS memory_embedding_vec_update AFTER UPDATE ON memory_embedding BEGIN
        ${updateDeleteStatements.join('')}
        ${updateInsertStatements.join('')}
      END
    `;
        // Create triggers
        db.exec(insertTriggerSQL);
        db.exec(updateTriggerSQL);
        // Note: Schema version is recorded by MigrationRunner, not here
        // MigrationRunner.recordVersion() will be called after successful migration
    }
    /**
     * Rollback migration (Down)
     * @param db 데이터베이스 인스턴스
     * @throws {Error} 롤백 실패 시
     */
    async down(db) {
        try {
            // Drop triggers
            db.exec('DROP TRIGGER IF EXISTS memory_embedding_vec_insert');
            db.exec('DROP TRIGGER IF EXISTS memory_embedding_vec_update');
            // Recreate triggers with old dimension condition (384 for TF-IDF)
            // Note: This restores the buggy behavior, but allows rollback
            db.exec(`
        CREATE TRIGGER IF NOT EXISTS memory_embedding_vec_insert AFTER INSERT ON memory_embedding BEGIN
          INSERT INTO memory_item_vec(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.dimensions = 384;
          
          INSERT INTO memory_item_vec_tfidf(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'tfidf' AND NEW.dimensions = 384 AND NEW.projection_type = 'native';
          
          INSERT INTO memory_item_vec_minilm(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'minilm' AND NEW.dimensions = 384 AND NEW.projection_type = 'native';
          
          INSERT INTO memory_item_vec_openai(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'openai' AND NEW.dimensions = 1536 AND NEW.projection_type = 'native';
          
          INSERT INTO memory_item_vec_gemini(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'gemini' AND NEW.dimensions = 768 AND NEW.projection_type = 'native';
        END
      `);
            db.exec(`
        CREATE TRIGGER IF NOT EXISTS memory_embedding_vec_update AFTER UPDATE ON memory_embedding BEGIN
          DELETE FROM memory_item_vec WHERE rowid = NEW.id;
          DELETE FROM memory_item_vec_tfidf WHERE rowid = NEW.id;
          DELETE FROM memory_item_vec_minilm WHERE rowid = NEW.id;
          DELETE FROM memory_item_vec_openai WHERE rowid = NEW.id;
          DELETE FROM memory_item_vec_gemini WHERE rowid = NEW.id;

          INSERT INTO memory_item_vec(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.dimensions = 384;
          
          INSERT INTO memory_item_vec_tfidf(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'tfidf' AND NEW.dimensions = 384 AND NEW.projection_type = 'native';
          
          INSERT INTO memory_item_vec_minilm(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'minilm' AND NEW.dimensions = 384 AND NEW.projection_type = 'native';
          
          INSERT INTO memory_item_vec_openai(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'openai' AND NEW.dimensions = 1536 AND NEW.projection_type = 'native';
          
          INSERT INTO memory_item_vec_gemini(rowid, embedding) 
          SELECT NEW.id, json_extract(NEW.embedding, '$')
          WHERE NEW.embedding_provider = 'gemini' AND NEW.dimensions = 768 AND NEW.projection_type = 'native';
        END
      `);
            // Remove schema version record
            db.prepare('DELETE FROM memento_schema_version WHERE version = ?').run('12.0');
        }
        catch (error) {
            throw new Error(`Failed to rollback migration: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
    /**
     * Validate after migration
     */
    async validateAfter(db) {
        // Check if any vec tables exist
        const hasTfidfTable = this.tableExists(db, 'memory_item_vec_tfidf');
        const hasMinilmTable = this.tableExists(db, 'memory_item_vec_minilm');
        const hasOpenaiTable = this.tableExists(db, 'memory_item_vec_openai');
        const hasGeminiTable = this.tableExists(db, 'memory_item_vec_gemini');
        const hasVecTable = this.tableExists(db, 'memory_item_vec');
        const hasAnyTable = hasVecTable || hasTfidfTable || hasMinilmTable || hasOpenaiTable || hasGeminiTable;
        // If no tables exist, triggers should not be created (migration should have skipped)
        if (!hasAnyTable) {
            // Verify triggers don't exist (they should have been skipped)
            const insertTriggerExists = this.triggerExists(db, 'memory_embedding_vec_insert');
            const updateTriggerExists = this.triggerExists(db, 'memory_embedding_vec_update');
            if (insertTriggerExists || updateTriggerExists) {
                throw new Error('Triggers exist but no vec tables found. This should not happen.');
            }
            // Migration skipped correctly - no validation needed
            return;
        }
        // Verify triggers exist
        if (!this.triggerExists(db, 'memory_embedding_vec_insert')) {
            throw new Error('memory_embedding_vec_insert trigger was not created');
        }
        if (!this.triggerExists(db, 'memory_embedding_vec_update')) {
            throw new Error('memory_embedding_vec_update trigger was not created');
        }
        // Verify trigger SQL contains correct dimension condition for TF-IDF (512)
        // Only check if memory_item_vec_tfidf table exists
        if (hasTfidfTable) {
            const insertTrigger = db
                .prepare(`
          SELECT sql FROM sqlite_master 
          WHERE type='trigger' AND name='memory_embedding_vec_insert'
        `)
                .get();
            if (!insertTrigger || !insertTrigger.sql) {
                throw new Error('memory_embedding_vec_insert trigger SQL not found');
            }
            // Check if trigger contains correct TF-IDF dimension condition
            if (!insertTrigger.sql.includes("dimensions = 512") ||
                !insertTrigger.sql.includes("embedding_provider = 'tfidf'")) {
                throw new Error('memory_embedding_vec_insert trigger does not contain correct TF-IDF dimension condition (512)');
            }
            const updateTrigger = db
                .prepare(`
          SELECT sql FROM sqlite_master 
          WHERE type='trigger' AND name='memory_embedding_vec_update'
        `)
                .get();
            if (!updateTrigger || !updateTrigger.sql) {
                throw new Error('memory_embedding_vec_update trigger SQL not found');
            }
            // Check if trigger contains correct TF-IDF dimension condition
            if (!updateTrigger.sql.includes("dimensions = 512") ||
                !updateTrigger.sql.includes("embedding_provider = 'tfidf'")) {
                throw new Error('memory_embedding_vec_update trigger does not contain correct TF-IDF dimension condition (512)');
            }
        }
    }
}
// Default export for migration detector
export default FixTfidfDimensionTriggerMigration;
//# sourceMappingURL=012-fix-tfidf-dimension-trigger.js.map