const { _electron: electron } = require('@playwright/test')
const {
  test: it
} = require('@playwright/test')
const { describe } = it
it.setTimeout(1000000)

const delay = require('./common/wait')
const log = require('./common/log')
const appOptions = require('./common/app-options')
const extendClient = require('./common/client-extend')
const { expect } = require('./common/expect')

const {
  setupSftpConnection,
  createFile,
  createFolder,
  enterFolder,
  navigateToParentFolder,
  deleteItem,
  selectAllContextMenu,
  verifyFileTransfersComplete,
  closeApp
} = require('./common/common')

describe('file-transfer-conflict-resolution', function () {
  it('should handle bidirectional file transfer conflicts with different resolution policies', async function () {
    const electronApp = await electron.launch(appOptions)
    const client = await electronApp.firstWindow()
    extendClient(client, electronApp)
    await delay(3500)
    log('018.file-transfer-conflict.spec.js: app launched')

    await setupSftpConnection(client)
    log('018.file-transfer-conflict.spec.js: sftp connected')
    await delay(2000)

    // Create a single test folder structure for all tests
    const timestamp = Date.now()
    const testFolder = `conflict-test-${timestamp}`

    try {
      // Create and prepare test environment
      await prepareTestEnvironment(client, testFolder)
      log('018.file-transfer-conflict.spec.js: test environment prepared')

      // Test conflict policies in both directions
      await testAllConflictPolicies(client, testFolder)
      log('018.file-transfer-conflict.spec.js: conflict policies tested')
    } finally {
      // Clean up test folders once at the end
      await cleanupTestFolders(client, testFolder)
      log('018.file-transfer-conflict.spec.js: test folders cleaned')
    }

    await closeApp(electronApp, __filename)
    log('018.file-transfer-conflict.spec.js: app closed')
  })
})

async function prepareTestEnvironment (client, testFolder) {
  // Create main test folder in both locations
  await createFolder(client, 'local', testFolder)
  await delay(1000)
  await createFolder(client, 'remote', testFolder)
  await delay(1000)

  // Enter both folders
  await enterFolder(client, 'local', testFolder)
  await delay(1000)
  await enterFolder(client, 'remote', testFolder)
  await delay(1000)

  // Create test files and folders in local only
  const testFiles = [
    'test-file-1.txt',
    'test-file-2.txt',
    'test-file-3.txt'
  ]

  const testFolders = [
    'test-folder-1',
    'test-folder-2',
    'test-folder-3'
  ]

  // Create files in local
  for (const fileName of testFiles) {
    await createFile(client, 'local', fileName)
    await delay(500)
  }

  // Create folders in local
  for (const folderName of testFolders) {
    await createFolder(client, 'local', folderName)
    await delay(500)
  }

  // Now upload everything to the remote to create identical structure
  await uploadAllToRemote(client)
}

async function uploadAllToRemote (client) {
  // Select all local items
  await selectAllContextMenu(client, 'local')
  await delay(1000)

  // Upload to remote
  await client.rightClick('.session-current .file-list.local .sftp-item.selected', 10, 10)
  await delay(1000)
  await client.click('.ant-dropdown:not(.ant-dropdown-hidden) .ant-dropdown-menu-item .anticon.anticon-cloud-upload')
  await delay(3000)

  // Wait for transfers to complete
  await verifyFileTransfersComplete(client)
  await delay(1000)
}

async function testAllConflictPolicies (client, testFolder) {
  // Test each policy for local to remote transfers
  await testConflictResolution(client, 'overwrite', 'local', 'remote')
  await testConflictResolution(client, 'rename', 'local', 'remote')
  await testConflictResolution(client, 'skip', 'local', 'remote')

  // Test each policy for remote to local transfers
  // await testConflictResolution(client, 'overwrite', 'remote', 'local')
  // await testConflictResolution(client, 'rename', 'remote', 'local')
  // await testConflictResolution(client, 'skip', 'remote', 'local')
}

async function testConflictResolution (client, policy, fromType, toType) {
  // Select all items in the source panel
  const selectedItems = await selectAllItems(client, fromType)
  await delay(1500)

  // Initiate transfer
  const isUpload = fromType === 'local'
  await client.rightClick(`.session-current .file-list.${fromType} .sftp-item.selected`, 10, 10)
  await delay(1500)

  // Click appropriate transfer menu item
  const menuIconClass = isUpload ? 'cloud-upload' : 'cloud-download'
  await client.click(`.ant-dropdown:not(.ant-dropdown-hidden) .ant-dropdown-menu-item .anticon.anticon-${menuIconClass}`)
  await delay(3000)

  // Handle conflict resolution based on policy
  if (policy === 'skip') {
    await client.click('.custom-modal-footer button:has-text("Skip all")')
    // Debug: Check if modal closes after click
    await delay(1000)
    if (await client.elemExist('.custom-modal-container')) {
      await client.click('.custom-modal-footer button:has-text("Skip all")')
    }
  } else if (policy === 'overwrite') {
    // Check for first conflict item type (file vs folder) and click appropriate button
    const isFolderConflict = await client.elemExist('.custom-modal-footer button:has-text("Merge all")')
    if (isFolderConflict) {
      await client.click('.custom-modal-footer button:has-text("Merge all")')
    } else {
      await client.click('.custom-modal-footer button:has-text("Overwrite all")')
    }
  } else if (policy === 'rename') {
    await client.click('.custom-modal-footer button:has-text("Rename all")')
  } else {
    throw new Error(`Unsupported policy: ${policy}`)
  }

  await delay(5000)

  // Wait for transfers to complete for overwrite and rename
  if (policy !== 'skip') {
    await verifyFileTransfersComplete(client)
  } else {
    // For skip, we've already handled each conflict manually
    await delay(2000)
  }

  // Verify results based on policy
  if (policy === 'rename') {
    // Verify renamed items exist in destination (with rename- pattern)
    const renamedItems = await client.locator(`.session-current .file-list.${toType} .sftp-item[title*="(rename-"]`)
    const count = await renamedItems.count()
    expect(count).toBeGreaterThan(0, `Expected to find renamed items from ${fromType} to ${toType} with policy ${policy}`)
  } else if (policy === 'overwrite') {
    // For overwrite, just verify the original count of items is maintained
    const items = await client.locator(`.session-current .file-list.${toType} .real-file-item`)
    const count = await items.count()
    expect(count).toBe(selectedItems, `Expected to find ${selectedItems} items in ${toType} after overwrite`)
  }
}

async function selectAllItems (client, type) {
  // First deselect everything by clicking empty space
  await client.click(`.session-current .file-list.${type} .sftp-item`)
  await delay(500)

  // Use selection context menu to select all real file items
  await selectAllContextMenu(client, type)
  await delay(1000)

  // Count and return the number of selected items
  const selectedItems = await client.locator(`.session-current .file-list.${type} .sftp-item.selected`).count()
  expect(selectedItems).toBeGreaterThan(0, `Expected to select items in ${type}`)

  return selectedItems
}

// async function handleSkipForEachItem (client, expectedItemCount) {
//   // For folders with files inside, we may have more conflicts than the base item count
//   // To handle this, we'll track the current conflict index and click Skip until all are done
//   let conflictsHandled = 0
//   // let timeWithoutConflict = 0
//   const waitInterval = 2000 // Time to wait between checks
//   // Continue until we have no more conflicts for a reasonable time
//   while (conflictsHandled < expectedItemCount) {
//     await client.click('.custom-modal-footer button span:text-is("Skip")')
//     conflictsHandled++

//     // Wait for a short time before checking again
//     await delay(waitInterval)
//   }

//   console.log(`Total conflicts skipped: ${conflictsHandled}`)

//   // We should have at least as many conflicts as selected items
//   expect(conflictsHandled).toBeGreaterThanOrEqual(expectedItemCount,
//     `Expected at least ${expectedItemCount} conflicts to be skipped, but only skipped ${conflictsHandled}`)
// }

async function cleanupTestFolders (client, testFolder) {
  // Navigate back to parent folders (if not already there)
  // Check if we need to navigate back
  const localPathInput = await client.getValue('.session-current .sftp-local-section .sftp-title input')
  if (localPathInput.includes(testFolder)) {
    await navigateToParentFolder(client, 'local')
    await delay(1000)
  }

  const remotePathInput = await client.getValue('.session-current .sftp-remote-section .sftp-title input')
  if (remotePathInput.includes(testFolder)) {
    await navigateToParentFolder(client, 'remote')
    await delay(1000)
  }

  // Delete test folders
  await deleteItem(client, 'local', testFolder)
  await delay(1000)
  await deleteItem(client, 'remote', testFolder)
  await delay(1000)
}
