const {
  test: it, expect
} = require('@playwright/test')
const { describe } = it
const { listWidgets } = require('../../src/app/widgets/load-widget')
const { widgetRun } = require('../../src/app/widgets/widget-rename')
const fs = require('fs/promises')
const path = require('path')

it.setTimeout(100000)

describe('rename-widget', function () {
  let testDir = null

  async function createTestFiles () {
    testDir = path.join(process.cwd(), 'temp-rename-test-' + Date.now())
    await fs.mkdir(testDir)

    // Create test files
    await fs.writeFile(path.join(testDir, 'file1.txt'), 'Content 1')
    await fs.writeFile(path.join(testDir, 'file2.txt'), 'Content 2')
    await fs.writeFile(path.join(testDir, 'file3.jpg'), 'Image content')

    // Create a subdirectory with a file
    const subDir = path.join(testDir, 'subfolder')
    await fs.mkdir(subDir)
    await fs.writeFile(path.join(subDir, 'subfile.txt'), 'Sub content')
  }

  async function cleanup () {
    if (testDir) {
      try {
        await fs.rm(testDir, { recursive: true, force: true })
      } catch (err) {
        console.error('Cleanup error:', err)
      }
    }
  }

  it.beforeEach(async () => {
    await createTestFiles()
  })

  it.afterEach(async () => {
    await cleanup()
  })

  it('should have rename widget available', async function () {
    const widgets = listWidgets()
    expect(Array.isArray(widgets)).toBe(true)

    const renameWidget = widgets.find(w => w.id === 'rename')
    expect(renameWidget).toBeTruthy()
    expect(renameWidget.info.name).toBe('File Renamer')
  })

  it('should rename files with simple pattern', async function () {
    const renameResult = await widgetRun({
      directory: testDir,
      template: '{name}-renamed.{ext}',
      fileTypes: '*',
      includeSubfolders: false
    })

    expect(renameResult.success).toBe(true)
    expect(renameResult.totalRenamed).toBe(3) // Should rename 3 files in the main directory

    // Check if files were renamed correctly
    const renamedFiles = await fs.readdir(testDir)
    expect(renamedFiles).toContain('file1-renamed.txt')
    expect(renamedFiles).toContain('file2-renamed.txt')
    expect(renamedFiles).toContain('file3-renamed.jpg')
  })

  it('should rename with sequential numbers', async function () {
    const renameResult = await widgetRun({
      directory: testDir,
      template: 'myfile-{n:3}.{ext}',
      fileTypes: '*',
      startNumber: 10,
      includeSubfolders: false
    })

    expect(renameResult.success).toBe(true)

    const renamedFiles = await fs.readdir(testDir)
    expect(renamedFiles).toContain('myfile-010.txt')
    expect(renamedFiles).toContain('myfile-011.txt')
    expect(renamedFiles).toContain('myfile-012.jpg')
  })

  it('should filter by file type', async function () {
    const renameResult = await widgetRun({
      directory: testDir,
      template: '{name}-{n}.{ext}',
      fileTypes: 'txt',
      includeSubfolders: false
    })

    expect(renameResult.success).toBe(true)
    expect(renameResult.totalRenamed).toBe(2) // Should only rename .txt files

    const renamedFiles = await fs.readdir(testDir)
    // file3.jpg should remain unchanged
    expect(renamedFiles).toContain('file3.jpg')
  })

  it('should include subfolders when enabled', async function () {
    const renameResult = await widgetRun({
      directory: testDir,
      template: '{parent}-{name}-{n}.{ext}',
      fileTypes: '*',
      includeSubfolders: true
    })

    expect(renameResult.success).toBe(true)
    expect(renameResult.totalRenamed).toBe(4) // All files including subfolder file

    // Check subfolder file was renamed
    const subFiles = await fs.readdir(path.join(testDir, 'subfolder'))
    expect(subFiles[0]).toMatch(/subfolder-subfile-\d\.txt/)
  })

  it('should handle template with dates and random', async function () {
    const renameResult = await widgetRun({
      directory: testDir,
      template: '{name}-{date}-{random}.{ext}',
      fileTypes: '*',
      includeSubfolders: false
    })

    expect(renameResult.success).toBe(true)

    // Verify that files were renamed with date and random pattern
    const renamedFiles = await fs.readdir(testDir)
    const datePattern = /\d{4}-\d{2}-\d{2}/

    for (const file of renamedFiles) {
      // If it's a directory, skip
      const stats = await fs.stat(path.join(testDir, file))
      if (stats.isDirectory()) continue

      // Each renamed file should have a date pattern and a random substring
      expect(file).toMatch(datePattern)
      expect(file).toMatch(/[a-z0-9]{6}/)
    }
  })

  it('should preserve filename case when enabled', async function () {
    // Create a file with mixed case
    await fs.writeFile(path.join(testDir, 'MixedCase.txt'), 'Mixed case content')

    const renameResult = await widgetRun({
      directory: testDir,
      template: '{name}-renamed.{ext}',
      fileTypes: '*',
      preserveCase: true,
      includeSubfolders: false
    })

    expect(renameResult.success).toBe(true)

    const renamedFiles = await fs.readdir(testDir)
    expect(renamedFiles).toContain('MixedCase-renamed.txt')
  })

  it('should handle error when directory does not exist', async function () {
    const renameResult = await widgetRun({
      directory: '/path/that/does/not/exist',
      template: '{name}-renamed.{ext}',
      fileTypes: '*'
    })

    expect(renameResult.success).toBe(false)
    expect(renameResult.error).toBeTruthy()
  })

  it('should reject templates that escape the source directory', async function () {
    const escapedPath = path.join(path.dirname(testDir), 'escaped-1.txt')
    const renameResult = await widgetRun({
      directory: testDir,
      template: '../escaped-{n}.{ext}',
      fileTypes: 'txt',
      includeSubfolders: false
    })

    expect(renameResult.success).toBe(false)
    expect(renameResult.error).toContain('path separators')

    const renamedFiles = await fs.readdir(testDir)
    expect(renamedFiles).toContain('file1.txt')
    await expect(fs.stat(escapedPath)).rejects.toThrow()
  })
})
