'use strict';

// Helper function to safely create a table if it doesn't exist
async function createTableIfNotExists(queryInterface, tableName, tableDefinition) {
  const tableExists = await queryInterface.tableExists(tableName);
  if (!tableExists) {
    await queryInterface.createTable(tableName, tableDefinition);
  }
}

// Helper function to safely add an index if it doesn't exist
async function addIndexIfNotExists(queryInterface, tableName, fields, options) {
  try {
    // First check if table exists
    const tableExists = await queryInterface.tableExists(tableName);
    if (!tableExists) {
      // Table doesn't exist yet, skip index creation
      return;
    }

    // Check if index already exists
    const indexes = await queryInterface.showIndex(tableName);
    const indexName = options.name || `idx_${tableName}_${fields.join('_')}`;
    const indexExists = indexes.some(idx => idx.name === indexName);
    if (!indexExists) {
      await queryInterface.addIndex(tableName, fields, options);
    }
  } catch (error) {
    // If index already exists, ignore the error
    if (
      error.message &&
      (error.message.includes('already exists') ||
        error.message.includes('duplicate key value') ||
        (error.message.includes('relation') && error.message.includes('already exists')))
    ) {
      return;
    }
    // For other errors, try to add the index anyway (might be a different issue)
    try {
      await queryInterface.addIndex(tableName, fields, options);
    } catch (addError) {
      // If it's still an "already exists" error, ignore it
      if (
        addError.message &&
        (addError.message.includes('already exists') ||
          addError.message.includes('duplicate key value') ||
          (addError.message.includes('relation') && addError.message.includes('already exists')))
      ) {
        return;
      }
      throw addError;
    }
  }
}

module.exports = {
  async up(queryInterface, Sequelize) {
    // Create storage_assets table
    await createTableIfNotExists(queryInterface, 'storage_assets', {
      id: {
        type: Sequelize.UUID,
        defaultValue: Sequelize.UUIDV4,
        primaryKey: true,
      },
      file_name: {
        type: Sequelize.STRING(255),
        allowNull: false,
        comment: 'Original filename',
      },
      file_path: {
        type: Sequelize.TEXT,
        allowNull: false,
        comment: 'Storage path, URL, or S3 key',
      },
      file_size: {
        type: Sequelize.BIGINT,
        allowNull: false,
        comment: 'File size in bytes',
      },
      mime_type: {
        type: Sequelize.STRING(100),
        allowNull: true,
        comment: 'MIME type: video/mp4, application/json, text/plain, etc.',
      },
      checksum: {
        type: Sequelize.STRING(64),
        allowNull: true,
        comment: 'SHA-256 checksum for file deduplication and integrity',
      },
      storage_type: {
        type: Sequelize.STRING(50),
        allowNull: false,
        comment: 'Storage backend: local, aws-s3, cloudflare-r2, azure-blob',
      },
      storage_metadata: {
        type: Sequelize.JSONB,
        allowNull: true,
        comment: 'Storage-specific metadata: bucket, region, etc.',
      },
      upload_status: {
        type: Sequelize.STRING(20),
        defaultValue: 'completed',
        allowNull: false,
        comment: 'Upload status: pending, uploading, completed, failed',
      },
      uploaded_by: {
        type: Sequelize.UUID,
        allowNull: true,
        references: {
          model: 'users',
          key: 'id',
        },
        onUpdate: 'CASCADE',
        onDelete: 'SET NULL',
        comment: 'User who uploaded this asset',
      },
      uploaded_at: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.NOW,
        allowNull: false,
        comment: 'When the upload completed',
      },
      upload_error: {
        type: Sequelize.TEXT,
        allowNull: true,
        comment: 'Error message if upload failed',
      },
      is_deleted: {
        type: Sequelize.BOOLEAN,
        defaultValue: false,
        allowNull: false,
        comment: 'Soft delete flag',
      },
      deleted_at: {
        type: Sequelize.DATE,
        allowNull: true,
        comment: 'When the asset was deleted',
      },
      expires_at: {
        type: Sequelize.DATE,
        allowNull: true,
        comment: 'When this asset should be cleaned up (for retention policy)',
      },
      created_at: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.NOW,
        allowNull: false,
      },
      updated_at: {
        type: Sequelize.DATE,
        defaultValue: Sequelize.NOW,
        allowNull: false,
      },
    });

    // Add indexes for storage_assets table
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['storage_type'], {
      name: 'idx_storage_assets_storage_type',
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['upload_status'], {
      name: 'idx_storage_assets_upload_status',
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['checksum'], {
      name: 'idx_storage_assets_checksum',
      where: { checksum: { [Sequelize.Op.ne]: null } },
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['uploaded_by'], {
      name: 'idx_storage_assets_uploaded_by',
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['uploaded_at'], {
      name: 'idx_storage_assets_uploaded_at',
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['expires_at'], {
      name: 'idx_storage_assets_expires_at',
      where: { expires_at: { [Sequelize.Op.ne]: null } },
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['is_deleted'], {
      name: 'idx_storage_assets_is_deleted',
    });
    await addIndexIfNotExists(queryInterface, 'storage_assets', ['created_at'], {
      name: 'idx_storage_assets_created_at',
    });
  },

  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable('storage_assets');
  },
};
