'use strict';

/**
 * Migration: Convert targetPageId to targetPageSlug in ui_schema_json
 *
 * This migration converts navigation elements from using page UUIDs (targetPageId)
 * to using page slugs (targetPageSlug). This fixes the ID remapping issue when
 * pages are copied between environments (dev -> stage -> production).
 *
 * Slugs are unique within project+environment and identical across environments,
 * eliminating the need for ID remapping during publish.
 */
module.exports = {
  async up(queryInterface, Sequelize) {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      // Get all tour pages with their ui_schema_json
      const [tourPages] = await queryInterface.sequelize.query(
        `SELECT id, "projectId", environment, slug, ui_schema_json FROM tour_pages WHERE ui_schema_json IS NOT NULL`,
        { transaction },
      );

      // Build a lookup map: pageId -> { projectId, environment, slug }
      const pageInfoById = new Map();
      tourPages.forEach((page) => {
        pageInfoById.set(page.id, {
          projectId: page.projectId,
          environment: page.environment,
          slug: page.slug,
        });
      });

      // Process each page and convert targetPageId to targetPageSlug
      for (const page of tourPages) {
        try {
          const uiSchema =
            typeof page.ui_schema_json === 'string'
              ? JSON.parse(page.ui_schema_json)
              : page.ui_schema_json;

          if (!uiSchema || !Array.isArray(uiSchema.elements)) {
            continue;
          }

          let hasChanges = false;

          uiSchema.elements.forEach((element) => {
            // Convert targetPageId to targetPageSlug
            if (
              element.targetPageId &&
              typeof element.targetPageId === 'string'
            ) {
              const targetPageInfo = pageInfoById.get(element.targetPageId);
              if (targetPageInfo && targetPageInfo.slug) {
                // Only convert if target page is in the same project and environment
                if (
                  targetPageInfo.projectId === page.projectId &&
                  targetPageInfo.environment === page.environment
                ) {
                  element.targetPageSlug = targetPageInfo.slug;
                  delete element.targetPageId;
                  hasChanges = true;
                }
              }
            }
          });

          if (hasChanges) {
            await queryInterface.sequelize.query(
              `UPDATE tour_pages SET ui_schema_json = :json WHERE id = :id`,
              {
                replacements: {
                  json: JSON.stringify(uiSchema),
                  id: page.id,
                },
                type: Sequelize.QueryTypes.UPDATE,
                transaction,
              },
            );
          }
        } catch (parseError) {
          // Skip pages with invalid JSON
          console.warn(`Skipping page ${page.id}: ${parseError.message}`);
        }
      }

      await transaction.commit();
      console.log(
        'Migration complete: Converted targetPageId to targetPageSlug',
      );
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  },

  async down(queryInterface, Sequelize) {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      // Get all tour pages
      const [tourPages] = await queryInterface.sequelize.query(
        `SELECT id, "projectId", environment, slug, ui_schema_json FROM tour_pages WHERE ui_schema_json IS NOT NULL`,
        { transaction },
      );

      // Build lookup: (projectId, environment, slug) -> pageId
      const pageIdByKey = new Map();
      tourPages.forEach((page) => {
        const key = `${page.projectId}:${page.environment}:${page.slug}`;
        pageIdByKey.set(key, page.id);
      });

      // Process each page and convert targetPageSlug back to targetPageId
      for (const page of tourPages) {
        try {
          const uiSchema =
            typeof page.ui_schema_json === 'string'
              ? JSON.parse(page.ui_schema_json)
              : page.ui_schema_json;

          if (!uiSchema || !Array.isArray(uiSchema.elements)) {
            continue;
          }

          let hasChanges = false;

          uiSchema.elements.forEach((element) => {
            if (
              element.targetPageSlug &&
              typeof element.targetPageSlug === 'string'
            ) {
              const key = `${page.projectId}:${page.environment}:${element.targetPageSlug}`;
              const targetPageId = pageIdByKey.get(key);
              if (targetPageId) {
                element.targetPageId = targetPageId;
                delete element.targetPageSlug;
                hasChanges = true;
              }
            }
          });

          if (hasChanges) {
            await queryInterface.sequelize.query(
              `UPDATE tour_pages SET ui_schema_json = :json WHERE id = :id`,
              {
                replacements: {
                  json: JSON.stringify(uiSchema),
                  id: page.id,
                },
                type: Sequelize.QueryTypes.UPDATE,
                transaction,
              },
            );
          }
        } catch (parseError) {
          console.warn(`Skipping page ${page.id}: ${parseError.message}`);
        }
      }

      await transaction.commit();
      console.log(
        'Rollback complete: Converted targetPageSlug back to targetPageId',
      );
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  },
};
