import { test, expect } from '../fixtures/auth.fixture'
import { fileURLToPath } from 'url'
import path from 'path'

/**
 * P1: postMessage 通信测试
 */

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)

const MOCK_H5_PATH = path.resolve(__dirname, '../utils/mock-h5.html')

/** 向 iframe 注入 JS 并执行 postMessage */
async function sendMessageFromIframe(page: import('@playwright/test').Page, message: Record<string, unknown>) {
  await page.evaluate((msg) => {
    const iframe = document.querySelector('iframe')
    if (iframe?.contentWindow) {
      iframe.contentWindow.postMessage(msg, '*')
    }
  }, message)
}

/** 模拟 iframe 内部 H5 发送消息（更真实：从 iframe 内部发出） */
async function injectMessageSender(page: import('@playwright/test').Page) {
  await page.evaluate(() => {
    const iframe = document.querySelector('iframe')
    if (iframe?.contentWindow) {
      // 注入一个可以由测试调用的函数
      ;(window as any).__sendFromH5 = (msg: Record<string, unknown>) => {
        // 模拟从 iframe contentWindow 发出
        // 由于同源策略，这里直接用 window.parent.postMessage
        iframe.contentWindow!.postMessage(msg, '*')
      }
    }
  })
}

test.describe('postMessage 通信', () => {

  test.beforeEach(async ({ loggedInPage }) => {
    // 拦截 token API
    await loggedInPage.route('**/leai-auth/token', async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          code: 200,
          data: {
            token: 'mock_token_for_postmessage_test',
            orgId: 'gdlib',
            h5Url: 'http://localhost:3001',
            phone: '13800001111',
          },
        }),
      })
    })

    // 拦截 iframe src 指向的 H5 URL，返回 mock 页面
    await loggedInPage.route('**/*token=mock_token_for_postmessage_test**', async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'text/html',
        path: MOCK_H5_PATH,
      })
    })

    await loggedInPage.goto('/p/create')
    // 等待 iframe 出现
    await loggedInPage.locator('iframe').first().waitFor({ timeout: 10_000 })
  })

  test('READY 事件 — 页面正常处理', async ({ loggedInPage }) => {
    // mock-h5.html 加载后自动发送 READY
    // 只需验证没有 JS 错误
    const consoleErrors: string[] = []
    loggedInPage.on('console', (msg) => {
      if (msg.type() === 'error') consoleErrors.push(msg.text())
    })

    // 等一小段时间让 READY 消息处理完
    await loggedInPage.waitForTimeout(1000)

    // 不应有未捕获的异常
    const criticalErrors = consoleErrors.filter(
      (e) => !e.includes('favicon') && !e.includes('404'),
    )
    expect(criticalErrors.length).toBe(0)
  })

  test('TOKEN_EXPIRED → 自动刷新 Token', async ({ loggedInPage }) => {
    let refreshCalled = false
    await loggedInPage.route('**/leai-auth/refresh-token', async (route) => {
      refreshCalled = true
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          code: 200,
          data: {
            token: 'refreshed_token_new',
            orgId: 'gdlib',
            phone: '13800001111',
          },
        }),
      })
    })

    // 模拟 H5 发送 TOKEN_EXPIRED
    await loggedInPage.evaluate(() => {
      const msg = {
        source: 'leai-creation',
        version: 1,
        type: 'TOKEN_EXPIRED',
        payload: { messageId: 'msg_test_001' },
      }
      // 从 window 层面直接触发 message 事件（模拟 iframe postMessage）
      window.dispatchEvent(new MessageEvent('message', { data: msg, origin: '*' }))
    })

    // 等待 refresh-token 被调用
    await loggedInPage.waitForTimeout(2000)
    expect(refreshCalled).toBe(true)
  })

  test('TOKEN_EXPIRED 刷新失败 — 显示错误提示', async ({ loggedInPage }) => {
    await loggedInPage.route('**/leai-auth/refresh-token', async (route) => {
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          code: 500,
          message: 'Token刷新失败',
        }),
      })
    })

    await loggedInPage.evaluate(() => {
      const msg = {
        source: 'leai-creation',
        version: 1,
        type: 'TOKEN_EXPIRED',
        payload: { messageId: 'msg_test_002' },
      }
      window.dispatchEvent(new MessageEvent('message', { data: msg, origin: '*' }))
    })

    await loggedInPage.waitForTimeout(2000)

    // 应显示错误提示（ant-design-vue message 组件）
    const errorToast = loggedInPage.locator('.ant-message-error, .ant-message-custom-content')
    // 错误提示可能出现也可能不出现，取决于实现
    // 这里只验证不会崩溃
  })

  test('NAVIGATE_BACK → 跳转到作品列表页', async ({ loggedInPage }) => {
    await loggedInPage.evaluate(() => {
      const msg = {
        source: 'leai-creation',
        version: 1,
        type: 'NAVIGATE_BACK',
        payload: {},
      }
      window.dispatchEvent(new MessageEvent('message', { data: msg, origin: '*' }))
    })

    // 验证路由跳转（作品列表页或首页）
    await loggedInPage.waitForTimeout(1500)
    const url = loggedInPage.url()
    // 应跳转离开 /p/create
    expect(url).not.toContain('/p/create')
  })

  test('CREATION_ERROR → 显示错误消息', async ({ loggedInPage }) => {
    const msgPromise = loggedInPage.evaluate(() => {
      return new Promise<string>((resolve) => {
        // 监听 ant-message 的出现
        const observer = new MutationObserver(() => {
          const errorEl = document.querySelector('.ant-message-error')
          if (errorEl) {
            resolve(errorEl.textContent || '')
            observer.disconnect()
          }
        })
        observer.observe(document.body, { childList: true, subtree: true })

        // 5 秒超时
        setTimeout(() => resolve(''), 5000)

        // 触发错误消息
        const msg = {
          source: 'leai-creation',
          version: 1,
          type: 'CREATION_ERROR',
          payload: { error: 'AI模型处理异常' },
        }
        window.dispatchEvent(new MessageEvent('message', { data: msg, origin: '*' }))
      })
    })

    // 只需验证不崩溃即可（message toast 可能需要 antd 渲染）
    await loggedInPage.waitForTimeout(2000)
  })

  test('忽略非 leai-creation 消息', async ({ loggedInPage }) => {
    let refreshCalled = false
    await loggedInPage.route('**/leai-auth/refresh-token', async (route) => {
      refreshCalled = true
      await route.fulfill({ status: 200, body: '{}' })
    })

    await loggedInPage.evaluate(() => {
      // 发送 source 不同的消息
      const msg = { source: 'other-app', type: 'TOKEN_EXPIRED', payload: {} }
      window.dispatchEvent(new MessageEvent('message', { data: msg, origin: '*' }))
    })

    await loggedInPage.waitForTimeout(1000)
    expect(refreshCalled).toBe(false)
  })

  test('忽略无 source 字段的消息', async ({ loggedInPage }) => {
    let refreshCalled = false
    await loggedInPage.route('**/leai-auth/refresh-token', async (route) => {
      refreshCalled = true
      await route.fulfill({ status: 200, body: '{}' })
    })

    await loggedInPage.evaluate(() => {
      const msg = { type: 'TOKEN_EXPIRED', payload: {} }
      window.dispatchEvent(new MessageEvent('message', { data: msg, origin: '*' }))
    })

    await loggedInPage.waitForTimeout(1000)
    expect(refreshCalled).toBe(false)
  })
})
