import {
  comfyPageFixture as test,
  comfyExpect as expect
} from '@e2e/fixtures/ComfyPage'
import type { AppModeHelper } from '@e2e/fixtures/helpers/AppModeHelper'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import {
  saveCloseAndReopenInBuilder,
  setupBuilder
} from '@e2e/fixtures/utils/builderTestUtils'

const WIDGETS = ['seed', 'steps', 'cfg']

async function saveCloseAndReopenAsApp(
  comfyPage: ComfyPage,
  appMode: AppModeHelper,
  workflowName: string
) {
  await saveCloseAndReopenInBuilder(comfyPage, appMode, workflowName)
  await appMode.toggleAppMode()
}

test.describe('Builder input reordering', { tag: '@ui' }, () => {
  test.beforeEach(async ({ comfyPage }) => {
    await comfyPage.appMode.enableLinearMode()
    await comfyPage.settings.setSetting(
      'Comfy.AppBuilder.VueNodeSwitchDismissed',
      true
    )
  })

  test('Drag first input to last position', async ({ comfyPage }) => {
    const { appMode } = comfyPage
    await setupBuilder(comfyPage, undefined, WIDGETS)

    await appMode.steps.goToInputs()
    await expect(appMode.select.inputItemTitles).toHaveText(WIDGETS)

    await appMode.select.dragInputItem(0, 2)
    await expect(appMode.select.inputItemTitles).toHaveText([
      'steps',
      'cfg',
      'seed'
    ])

    await appMode.steps.goToPreview()
    await expect(appMode.select.previewWidgetLabels).toHaveText([
      'steps',
      'cfg',
      'seed'
    ])
  })

  test('Drag last input to first position', async ({ comfyPage }) => {
    const { appMode } = comfyPage
    await setupBuilder(comfyPage, undefined, WIDGETS)

    await appMode.steps.goToInputs()
    await expect(appMode.select.inputItemTitles).toHaveText(WIDGETS)

    await appMode.select.dragInputItem(2, 0)
    await expect(appMode.select.inputItemTitles).toHaveText([
      'cfg',
      'seed',
      'steps'
    ])

    await appMode.steps.goToPreview()
    await expect(appMode.select.previewWidgetLabels).toHaveText([
      'cfg',
      'seed',
      'steps'
    ])
  })

  test('Drag input to middle position', async ({ comfyPage }) => {
    const { appMode } = comfyPage
    await setupBuilder(comfyPage, undefined, WIDGETS)

    await appMode.steps.goToInputs()
    await expect(appMode.select.inputItemTitles).toHaveText(WIDGETS)

    await appMode.select.dragInputItem(0, 1)
    await expect(appMode.select.inputItemTitles).toHaveText([
      'steps',
      'seed',
      'cfg'
    ])

    await appMode.steps.goToPreview()
    await expect(appMode.select.previewWidgetLabels).toHaveText([
      'steps',
      'seed',
      'cfg'
    ])
  })

  test('Reorder in preview step reflects in app mode after save', async ({
    comfyPage
  }) => {
    const { appMode } = comfyPage
    await setupBuilder(comfyPage, undefined, WIDGETS)

    await appMode.steps.goToPreview()
    await expect(appMode.select.previewWidgetLabels).toHaveText(WIDGETS)

    await appMode.select.dragPreviewItem(0, 2)
    await expect(appMode.select.previewWidgetLabels).toHaveText([
      'steps',
      'cfg',
      'seed'
    ])

    const workflowName = `${Date.now()} reorder-preview`
    await saveCloseAndReopenAsApp(comfyPage, appMode, workflowName)

    await expect(appMode.linearWidgets).toBeVisible()
    await expect(appMode.select.previewWidgetLabels).toHaveText([
      'steps',
      'cfg',
      'seed'
    ])
  })

  test('Reorder inputs persists after save and reload', async ({
    comfyPage
  }) => {
    const { appMode } = comfyPage
    await setupBuilder(comfyPage, undefined, WIDGETS)

    await appMode.steps.goToInputs()
    await appMode.select.dragInputItem(0, 2)
    await expect(appMode.select.inputItemTitles).toHaveText([
      'steps',
      'cfg',
      'seed'
    ])

    const workflowName = `${Date.now()} reorder-persist`
    await saveCloseAndReopenAsApp(comfyPage, appMode, workflowName)

    await expect(appMode.linearWidgets).toBeVisible()
    await expect(appMode.select.previewWidgetLabels).toHaveText([
      'steps',
      'cfg',
      'seed'
    ])
  })

  test('Reordering inputs in one app does not corrupt another app', async ({
    comfyPage
  }, testInfo) => {
    // This test creates 2 apps, switches tabs 3 times, and enters builder 3
    // times — the default 15s timeout is insufficient in CI.
    testInfo.setTimeout(45_000)
    const { appMode } = comfyPage
    const app2Widgets = ['seed', 'steps']
    const app1Reordered = ['steps', 'cfg', 'seed']

    await test.step('Load both apps', async () => {
      await comfyPage.workflow.loadWorkflow('linear-basic-app-1')
      await comfyPage.workflow.loadWorkflow('linear-basic-app-2')
    })

    await test.step('Reorder app1 inputs', async () => {
      await comfyPage.workflow.switchToTab('linear-basic-app-1')
      await appMode.enterBuilder()
      await appMode.steps.goToInputs()
      await expect(appMode.select.inputItemTitles).toHaveText(WIDGETS)

      await appMode.select.dragInputItem(0, 2)
      await expect(appMode.select.inputItemTitles).toHaveText(app1Reordered)
    })

    await test.step('Verify app2 inputs are not corrupted', async () => {
      await appMode.footer.exitBuilder()
      await comfyPage.workflow.switchToTab('linear-basic-app-2')
      await appMode.enterBuilder()
      await appMode.steps.goToInputs()
      await expect(appMode.select.inputItemTitles).toHaveText(app2Widgets)
    })

    await test.step('Verify app1 reorder persisted', async () => {
      await appMode.footer.exitBuilder()
      await comfyPage.workflow.switchToTab('linear-basic-app-1')
      await appMode.enterBuilder()
      await appMode.steps.goToInputs()
      await expect(appMode.select.inputItemTitles).toHaveText(app1Reordered)
    })
  })
})
