import { test, expect, type Page } from '@playwright/test'

// 测试账号配置
const TEST_USERNAME = process.env.TEST_USERNAME || 'admin'
const TEST_PASSWORD = process.env.TEST_PASSWORD || '123456'

// 登录辅助函数
async function login(page: Page) {
  await page.goto('/login')
  await page.evaluate(() => {
    localStorage.clear()
    document.cookie.split(';').forEach((c) => {
      document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/')
    })
  })
  await page.reload()

  await page.getByPlaceholder('用户名').fill(TEST_USERNAME)
  await page.getByPlaceholder('密码').fill(TEST_PASSWORD)
  await page.getByRole('button', { name: '登录' }).click()
  await expect(page).not.toHaveURL(/\/login/, { timeout: 15000 })
}

test.describe('LiveStream 管理 - 搜索功能测试', () => {
  /**
   * 按 Stream SN 搜索
   */
  test('按 Stream SN 搜索 - 验证参数传递', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 设置 API 拦截来验证参数
    let requestBody: any = null
    await page.route('**/admin/live-stream/list', async (route) => {
      const request = route.request()
      if (request.method() === 'POST') {
        requestBody = request.postDataJSON()
      }
      await route.continue()
    })

    // 在 stream sn 搜索框输入
    await page.getByPlaceholder('stream sn').fill('stream_123')

    // 点击查询
    await page.getByRole('button', { name: '查询' }).click()
    await page.waitForTimeout(1000)

    // 验证请求参数中包含 streamSn
    expect(requestBody).not.toBeNull()
    expect(requestBody.streamSn).toBe('stream_123')
  })

  /**
   * 按 Name 搜索
   */
  test('按 Name 搜索 - 验证参数传递', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 设置 API 拦截
    let requestBody: any = null
    await page.route('**/admin/live-stream/list', async (route) => {
      const request = route.request()
      if (request.method() === 'POST') {
        requestBody = request.postDataJSON()
      }
      await route.continue()
    })

    // 在 name 搜索框输入
    await page.getByPlaceholder('name').fill('测试流')

    // 点击查询
    await page.getByRole('button', { name: '查询' }).click()
    await page.waitForTimeout(1000)

    // 验证请求参数中包含 name
    expect(requestBody).not.toBeNull()
    expect(requestBody.name).toBe('测试流')
  })

  /**
   * 按 LSS 搜索
   */
  test('按 LSS 搜索 - 验证参数传递', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 设置 API 拦截
    let requestBody: any = null
    await page.route('**/admin/live-stream/list', async (route) => {
      const request = route.request()
      if (request.method() === 'POST') {
        requestBody = request.postDataJSON()
      }
      await route.continue()
    })

    // 点击 LSS 下拉框
    await page.locator('.el-select').filter({ hasText: 'LSS' }).click()
    await page.waitForTimeout(300)

    // 选择第一个 LSS 选项（如果有）
    const firstOption = page.locator('.el-select-dropdown__item').first()
    if (await firstOption.isVisible()) {
      const lssValue = await firstOption.textContent()
      await firstOption.click()

      // 点击查询
      await page.getByRole('button', { name: '查询' }).click()
      await page.waitForTimeout(1000)

      // 验证请求参数中包含 lssId
      expect(requestBody).not.toBeNull()
      expect(requestBody.lssId).toBe(lssValue?.trim())
    }
  })

  /**
   * 按设备ID搜索
   */
  test('按设备ID搜索 - 验证参数传递', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 设置 API 拦截
    let requestBody: any = null
    await page.route('**/admin/live-stream/list', async (route) => {
      const request = route.request()
      if (request.method() === 'POST') {
        requestBody = request.postDataJSON()
      }
      await route.continue()
    })

    // 在设备ID搜索框输入
    await page.getByPlaceholder('设备ID').fill('EEE1')

    // 点击查询
    await page.getByRole('button', { name: '查询' }).click()
    await page.waitForTimeout(1000)

    // 验证请求参数中包含 cameraId
    expect(requestBody).not.toBeNull()
    expect(requestBody.cameraId).toBe('EEE1')
  })

  /**
   * 组合搜索 - 所有字段
   */
  test('组合搜索 - 多字段同时搜索', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 设置 API 拦截
    let requestBody: any = null
    await page.route('**/admin/live-stream/list', async (route) => {
      const request = route.request()
      if (request.method() === 'POST') {
        requestBody = request.postDataJSON()
      }
      await route.continue()
    })

    // 填入所有搜索条件
    await page.getByPlaceholder('stream sn').fill('stream_001')
    await page.getByPlaceholder('name').fill('测试')
    await page.getByPlaceholder('设备ID').fill('EEE1')

    // 点击查询
    await page.getByRole('button', { name: '查询' }).click()
    await page.waitForTimeout(1000)

    // 验证请求参数包含所有字段
    expect(requestBody).not.toBeNull()
    expect(requestBody.streamSn).toBe('stream_001')
    expect(requestBody.name).toBe('测试')
    expect(requestBody.cameraId).toBe('EEE1')
  })

  /**
   * 重置搜索条件
   */
  test('重置搜索条件 - 清空所有输入', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 填入搜索条件
    await page.getByPlaceholder('stream sn').fill('test-sn')
    await page.getByPlaceholder('name').fill('test-name')
    await page.getByPlaceholder('设备ID').fill('test-device')

    // 点击重置
    await page.getByRole('button', { name: '重置' }).click()
    await page.waitForTimeout(300)

    // 验证搜索条件已清空
    await expect(page.getByPlaceholder('stream sn')).toHaveValue('')
    await expect(page.getByPlaceholder('name')).toHaveValue('')
    await expect(page.getByPlaceholder('设备ID')).toHaveValue('')
  })
})

test.describe('LiveStream 管理 - BUG 回归测试', () => {
  /**
   * BUG 回归测试：按设备ID搜索应该只返回匹配的记录
   *
   * 问题描述：
   * - 前端已修复：searchForm.cameraId 参数现在会正确传递给 API
   * - 后端待修复：API 目前未实现 cameraId 过滤，返回所有数据
   *
   * 预期行为：
   * - 搜索设备ID "EEE1" 应该只返回 1 条记录
   * - 该记录的设备ID列应该显示 "EEE1"
   *
   * 当前状态：测试会失败，等待后端实现过滤
   */
  test('BUG: 按设备ID搜索 EEE1 应该只返回 1 条匹配记录', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })
    await page.waitForTimeout(500)

    // 在设备ID搜索框输入 "EEE1"
    await page.getByPlaceholder('设备ID').fill('EEE1')

    // 点击查询按钮
    await page.getByRole('button', { name: '查询' }).click()

    // 等待搜索结果加载
    await page.waitForTimeout(1000)

    // 验证：应该只有 1 条记录
    const tableRows = page.locator('tbody tr')
    const rowCount = await tableRows.count()
    expect(rowCount).toBe(1)

    // 验证：该记录的设备ID应该是 "EEE1"
    const firstRowDeviceId = await tableRows.first().locator('td').nth(3).textContent()
    expect(firstRowDeviceId?.trim()).toBe('EEE1')

    // 验证：分页显示 Total 1
    await expect(page.locator('.el-pagination')).toContainText('Total 1')
  })
})

test.describe('LiveStream 管理 - 页面功能测试', () => {
  test('LiveStream 管理页面正确显示', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 验证页面标题
    await expect(page.locator('text=LiveStream 管理')).toBeVisible()

    // 验证搜索表单元素
    await expect(page.getByPlaceholder('stream sn')).toBeVisible()
    await expect(page.getByPlaceholder('name')).toBeVisible()
    await expect(page.getByPlaceholder('设备ID')).toBeVisible()
    await expect(page.getByRole('button', { name: '查询' })).toBeVisible()
    await expect(page.getByRole('button', { name: '重置' })).toBeVisible()
    await expect(page.getByRole('button', { name: '新增' })).toBeVisible()

    // 验证表头
    await expect(page.locator('th:has-text("Stream SN"), th:has-text("stream sn")')).toBeVisible()
    await expect(page.locator('th:has-text("Name"), th:has-text("名称")')).toBeVisible()
    await expect(page.locator('th:has-text("LSS")')).toBeVisible()
    await expect(page.locator('th:has-text("Device ID"), th:has-text("设备ID")')).toBeVisible()
  })

  test('打开新增 LiveStream 抽屉', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 点击新增按钮
    await page.getByRole('button', { name: '新增' }).click()

    // 验证抽屉打开
    const drawer = page.locator('.el-drawer').filter({ hasText: '新增 Live Stream' })
    await expect(drawer).toBeVisible({ timeout: 5000 })

    // 验证表单元素
    await expect(drawer.locator('label:has-text("名称")')).toBeVisible()
    await expect(drawer.locator('label:has-text("LSS 节点")')).toBeVisible()
    await expect(drawer.locator('label:has-text("摄像头")')).toBeVisible()

    // 关闭抽屉
    await drawer.getByRole('button', { name: '取消' }).click()
    await expect(drawer).not.toBeVisible({ timeout: 5000 })
  })

  test('分页功能正常', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForTimeout(1000)

    // 验证分页组件存在
    const pagination = page.locator('.el-pagination')
    await expect(pagination).toBeVisible()

    // 验证 Total 显示
    await expect(pagination.locator('text=/Total \\d+/')).toBeVisible()
  })

  test('从侧边栏导航到 LiveStream 管理', async ({ page }) => {
    await login(page)

    // 点击侧边栏 LiveStream 管理菜单项
    await page.getByText('LiveStream 管理').first().click()

    // 验证跳转到 LiveStream 管理页面
    await expect(page).toHaveURL(/\/live-stream/)
    await expect(page.locator('text=LiveStream 管理')).toBeVisible()
  })
})

test.describe('LiveStream 管理 - CodeEditor 组件测试 (Bash模式)', () => {
  /**
   * 测试 CodeEditor Bash 模式 - 头部显示
   */
  test('CodeEditor Bash模式 - 验证头部显示Bash Script标签和复制按钮', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await expect(viewLink).toBeVisible({ timeout: 5000 })
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 验证 CodeEditor 头部显示 Bash Script 标签
    const codeEditor = dialog.locator('.code-editor')
    await expect(codeEditor).toBeVisible()
    await expect(codeEditor.locator('.editor-header')).toBeVisible()
    await expect(codeEditor.locator('.file-type')).toContainText('Bash Script')

    // 验证 Copy 按钮存在
    await expect(codeEditor.locator('button:has-text("复制"), button:has-text("Copy")')).toBeVisible()

    // 验证 Bash 模式没有格式化按钮
    await expect(codeEditor.locator('button:has-text("格式化")')).not.toBeVisible()
  })

  /**
   * 测试 CodeEditor Bash 模式 - 复制功能
   */
  test('CodeEditor Bash模式 - 复制按钮功能', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 点击复制按钮
    const copyButton = dialog.locator('.code-editor button:has-text("复制"), .code-editor button:has-text("Copy")')
    await copyButton.click()

    // 验证复制成功提示
    await expect(page.locator('.el-message--success')).toBeVisible({ timeout: 3000 })
  })

  /**
   * 测试 CodeEditor Bash 模式 - 编辑器可编辑
   */
  test('CodeEditor Bash模式 - 编辑器可编辑', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 验证编辑器存在并可以编辑
    const codeEditor = dialog.locator('.code-editor')
    const editorContent = codeEditor.locator('.cm-content')
    await expect(editorContent).toBeVisible()

    // 尝试在编辑器中输入内容
    await editorContent.click()
    await page.keyboard.press('End')
    await page.keyboard.type('\n# Test comment')

    // 验证内容已添加
    await expect(editorContent).toContainText('# Test comment')
  })

  /**
   * 测试 CodeEditor Bash 模式 - 更新按钮存在
   */
  test('CodeEditor Bash模式 - 弹窗包含关闭和更新按钮', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 验证关闭和更新按钮存在
    await expect(dialog.locator('button:has-text("关闭"), button:has-text("Close")')).toBeVisible()
    await expect(dialog.locator('button:has-text("更新"), button:has-text("Update")')).toBeVisible()

    // 点击关闭按钮
    await dialog.locator('button:has-text("关闭"), button:has-text("Close")').click()
    await expect(dialog).not.toBeVisible({ timeout: 5000 })
  })

  /**
   * 测试 CodeEditor Bash 模式 - 图标颜色正确（绿色）
   */
  test('CodeEditor Bash模式 - 图标显示为绿色', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 验证图标有 icon-bash 类（对应绿色）
    const codeEditor = dialog.locator('.code-editor')
    await expect(codeEditor.locator('.icon-bash')).toBeVisible()
  })

  /**
   * 测试 CodeEditor Bash 模式 - 更新命令模板并验证保存成功
   */
  test('CodeEditor Bash模式 - 更新命令模板并验证保存成功', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 获取编辑器
    const codeEditor = dialog.locator('.code-editor')
    const editorContent = codeEditor.locator('.cm-content')

    // 生成唯一标识用于验证更新
    const timestamp = Date.now()
    const testComment = `# Test update at ${timestamp}`

    // 在编辑器末尾添加测试注释
    await editorContent.click()
    await page.keyboard.press('Meta+End')
    await page.keyboard.type(`\n${testComment}`)

    // 点击更新按钮
    const updateButton = dialog.locator('button:has-text("更新"), button:has-text("Update")')
    await updateButton.click()

    // 等待更新成功提示
    await expect(page.locator('.el-message--success')).toBeVisible({ timeout: 5000 })

    // 等待弹窗关闭
    await expect(dialog).not.toBeVisible({ timeout: 5000 })

    // 重新打开命令模板弹窗验证内容已保存
    await page.waitForTimeout(500)
    await viewLink.click()

    // 等待弹窗重新打开
    const dialogReopened = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialogReopened).toBeVisible({ timeout: 5000 })

    // 验证内容包含我们添加的测试注释
    const editorContentReopened = dialogReopened.locator('.cm-content')
    await expect(editorContentReopened).toContainText(timestamp.toString())
  })

  /**
   * 测试 CodeEditor Bash 模式 - 修改全部内容并验证保存
   */
  test('CodeEditor Bash模式 - 替换全部命令模板并验证保存', async ({ page }) => {
    await login(page)
    await page.goto('/live-stream')

    // 等待表格加载
    await page.waitForSelector('tbody tr', { timeout: 10000 })

    // 点击命令模板列的"查看"链接
    const viewLink = page.locator('tbody tr').first().locator('a:has-text("查看"), a:has-text("View")')
    await viewLink.click()

    // 等待命令模板弹窗打开
    const dialog = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialog).toBeVisible({ timeout: 5000 })

    // 获取编辑器
    const codeEditor = dialog.locator('.code-editor')
    const editorContent = codeEditor.locator('.cm-content')

    // 保存原始内容以便恢复
    const originalContent = await editorContent.textContent()

    // 生成唯一标识用于验证更新
    const timestamp = Date.now()
    const newScript = `#!/bin/bash
# Updated script at ${timestamp}
echo "Test script"
ffmpeg -i {RTSP_URL} -c copy output.mp4`

    // 全选并替换内容
    await editorContent.click()
    await page.keyboard.press('Meta+a')
    await page.keyboard.type(newScript)

    // 点击更新按钮
    const updateButton = dialog.locator('button:has-text("更新"), button:has-text("Update")')
    await updateButton.click()

    // 等待更新成功提示
    await expect(page.locator('.el-message--success')).toBeVisible({ timeout: 5000 })

    // 等待弹窗关闭
    await expect(dialog).not.toBeVisible({ timeout: 5000 })

    // 重新打开验证内容
    await page.waitForTimeout(500)
    await viewLink.click()

    const dialogReopened = page.locator('.el-dialog').filter({ hasText: '命令模板' })
    await expect(dialogReopened).toBeVisible({ timeout: 5000 })

    const editorContentReopened = dialogReopened.locator('.cm-content')
    await expect(editorContentReopened).toContainText(`Updated script at ${timestamp}`)
    await expect(editorContentReopened).toContainText('echo "Test script"')

    // 恢复原始内容
    if (originalContent) {
      await editorContentReopened.click()
      await page.keyboard.press('Meta+a')
      await page.keyboard.type(originalContent)
      await dialogReopened.locator('button:has-text("更新"), button:has-text("Update")').click()
      await page.waitForTimeout(1000)
    }
  })
})
