/**
 * 教师端全功能 Web 测试
 * 测试范围：教师端所有页面路由
 */
import { expect, test } from "@playwright/test"
import fs from "node:fs"
import path from "node:path"

const TEACHER_EMAIL = "t_chinese_1@xiaoxue.edu.cn"
const TEACHER_PASSWORD = "123456"

// 教师端所有路由
const TEACHER_ROUTES: { category: string; routes: string[] }[] = [
  {
    category: "Dashboard",
    routes: ["/teacher/dashboard"],
  },
  {
    category: "Textbooks",
    routes: ["/teacher/textbooks"],
  },
  {
    category: "Exams",
    routes: [
      "/teacher/exams",
      "/teacher/exams/all",
      "/teacher/exams/create",
    ],
  },
  {
    category: "Homework",
    routes: [
      "/teacher/homework",
      "/teacher/homework/assignments",
      "/teacher/homework/assignments/create",
      "/teacher/homework/submissions",
    ],
  },
  {
    category: "Grades",
    routes: [
      "/teacher/grades",
      "/teacher/grades/entry",
      "/teacher/grades/stats",
      "/teacher/grades/analytics",
    ],
  },
  {
    category: "Question Bank",
    routes: ["/teacher/questions"],
  },
  {
    category: "Class Management",
    routes: [
      "/teacher/classes",
      "/teacher/classes/my",
      "/teacher/classes/students",
      "/teacher/classes/schedule",
    ],
  },
  {
    category: "Course Plans",
    routes: ["/teacher/course-plans"],
  },
  {
    category: "Lesson Plans",
    routes: [
      "/teacher/lesson-plans",
      "/teacher/lesson-plans/new",
    ],
  },
  {
    category: "Attendance",
    routes: [
      "/teacher/attendance",
      "/teacher/attendance/sheet",
      "/teacher/attendance/stats",
    ],
  },
  {
    category: "Schedule Changes",
    routes: ["/teacher/schedule-changes"],
  },
  {
    category: "Diagnostic",
    routes: ["/teacher/diagnostic"],
  },
  {
    category: "Electives",
    routes: ["/teacher/elective"],
  },
  {
    category: "Management",
    routes: [
      "/management/grade/classes",
      "/management/grade/insights",
    ],
  },
  {
    category: "Announcements",
    routes: ["/announcements"],
  },
  {
    category: "Messages",
    routes: ["/messages"],
  },
]

// 需要登录后从列表页抓取链接的详情页模式
const DETAIL_PATTERNS: { category: string; listRoute: string; linkPattern: string }[] = [
  { category: "Textbooks Detail", listRoute: "/teacher/textbooks", linkPattern: "/teacher/textbooks/" },
  { category: "Classes Detail", listRoute: "/teacher/classes/my", linkPattern: "/teacher/classes/my/" },
  { category: "Course Plans Detail", listRoute: "/teacher/course-plans", linkPattern: "/teacher/course-plans/" },
  { category: "Lesson Plans Detail", listRoute: "/teacher/lesson-plans", linkPattern: "/teacher/lesson-plans/" },
]

interface TestResult {
  url: string
  category: string
  status: "passed" | "failed" | "warning"
  httpStatus: number | null
  finalUrl: string
  errors: string[]
  warnings: string[]
}

const allResults: TestResult[] = []

function addResult(result: TestResult): void {
  allResults.push(result)
}

function generateReport(): string {
  const lines: string[] = []
  const passed = allResults.filter((r) => r.status === "passed").length
  const failed = allResults.filter((r) => r.status === "failed").length
  const warnings = allResults.filter((r) => r.status === "warning").length
  const total = allResults.length

  lines.push("# 教师端 Web 功能测试报告 (v2)")
  lines.push("")
  lines.push(`> 测试日期：${new Date().toISOString().replace("T", " ").slice(0, 19)}`)
  lines.push("> 测试范围：所有教师端页面功能")
  lines.push("> 测试工具：Playwright + Chromium")
  lines.push(`> 测试账号：${TEACHER_EMAIL}`)
  lines.push("")
  lines.push("---")
  lines.push("")
  lines.push("## 一、测试概览")
  lines.push("")
  lines.push("| 指标 | 数值 |")
  lines.push("|------|------|")
  lines.push(`| 总测试页面数 | ${total} |`)
  lines.push(`| ✅ 通过 | ${passed} |`)
  lines.push(`| ❌ 失败 | ${failed} |`)
  lines.push(`| ⚠️ 警告 | ${warnings} |`)
  lines.push(`| 通过率 | ${total > 0 ? ((passed / total) * 100).toFixed(1) : "N/A"}% |`)
  lines.push("")
  lines.push("---")
  lines.push("")
  lines.push("## 二、页面测试详情")
  lines.push("")

  // 按类别分组
  const byCategory = new Map<string, TestResult[]>()
  for (const r of allResults) {
    const cat = r.category
    if (!byCategory.has(cat)) byCategory.set(cat, [])
    byCategory.get(cat)!.push(r)
  }

  for (const [category, results] of byCategory) {
    lines.push(`### ${category}`)
    lines.push("")
    lines.push("| 页面 | HTTP状态 | 结果 | 备注 |")
    lines.push("|------|----------|------|------|")

    for (const r of results) {
      const icon = r.status === "passed" ? "✅" : r.status === "warning" ? "⚠️" : "❌"
      const notes: string[] = []
      if (r.finalUrl !== r.url) notes.push(`重定向: ${r.finalUrl}`)
      if (r.errors.length > 0) notes.push(`错误: ${r.errors.slice(0, 2).join("; ")}`)
      if (r.warnings.length > 0) notes.push(`警告: ${r.warnings.slice(0, 2).join("; ")}`)
      const noteStr = notes.length > 0 ? notes.join("<br>") : "-"

      lines.push(`| ${icon} \`${r.url}\` | ${r.httpStatus ?? "-"} | ${r.status} | ${noteStr} |`)
    }
    lines.push("")
  }

  // 失败详情
  const failedResults = allResults.filter((r) => r.status === "failed")
  if (failedResults.length > 0) {
    lines.push("---")
    lines.push("")
    lines.push("## 三、失败页面详情")
    lines.push("")
    for (const r of failedResults) {
      lines.push(`### ❌ \`${r.url}\``)
      lines.push("")
      lines.push(`- **分类**: ${r.category}`)
      lines.push(`- **HTTP状态**: ${r.httpStatus ?? "-"}`)
      if (r.finalUrl !== r.url) lines.push(`- **重定向**: ${r.finalUrl}`)
      if (r.errors.length > 0) {
        lines.push("- **错误信息**:")
        for (const e of r.errors) lines.push(`  - ${e}`)
      }
      lines.push("")
    }
  }

  // 警告详情
  const warningResults = allResults.filter((r) => r.status === "warning")
  if (warningResults.length > 0) {
    lines.push("---")
    lines.push("")
    lines.push("## 四、警告页面")
    lines.push("")
    for (const r of warningResults) {
      lines.push(`### ⚠️ \`${r.url}\``)
      lines.push("")
      lines.push(`- **分类**: ${r.category}`)
      if (r.warnings.length > 0) {
        for (const w of r.warnings) lines.push(`  - ${w}`)
      }
      lines.push("")
    }
  }

  lines.push("---")
  lines.push("")
  lines.push(`*报告自动生成于 ${new Date().toISOString().replace("T", " ").slice(0, 19)}*`)

  return lines.join("\n")
}

test.describe("Teacher Full Web Test", () => {
  test.setTimeout(300000) // 5 minutes total

  test("login and test all teacher pages", async ({ page }) => {
    // ====== Step 1: Login ======
    console.log("\n>>> 登录教师账号...")
    await page.goto("/login")
    await page.waitForLoadState("networkidle")

    // 填表登录
    const emailInput = page.locator('input[name="email"]')
    if ((await emailInput.count()) === 0) {
      await page.locator('input[type="email"]').first().waitFor({ state: "visible", timeout: 5000 })
    }
    await page.locator('input[type="email"], input[name="email"]').first().fill(TEACHER_EMAIL)
    await page.locator('input[type="password"], input[name="password"]').first().fill(TEACHER_PASSWORD)

    // 点击登录
    const submitBtn = page.locator('button[type="submit"]')
    if ((await submitBtn.count()) > 0) {
      await submitBtn.first().click()
    } else {
      await page.getByRole("button", { name: /Sign In|登录/i }).click()
    }
    await page.waitForLoadState("networkidle")
    await page.waitForTimeout(2000)

    console.log(`登录后 URL: ${page.url()}`)
    expect(page.url()).not.toContain("/login")

    // ====== Step 2: Test all routes ======
    for (const { category, routes } of TEACHER_ROUTES) {
      for (const route of routes) {
        console.log(`\n  测试: ${category} - ${route}`)
        const result = await testSinglePage(page, route, category)
        addResult(result)
      }
    }

    // ====== Step 3: Discover and test detail pages ======
    console.log("\n\n>>> 发现详情页链接...")
    for (const { category, listRoute, linkPattern } of DETAIL_PATTERNS) {
      const detailUrls = await discoverDetailLinks(page, listRoute, linkPattern)
      if (detailUrls.length > 0) {
        console.log(`\n  ${category}: ${detailUrls.length} 个详情页`)
        for (const detailUrl of detailUrls.slice(0, 2)) {
          const result = await testSinglePage(page, detailUrl, `${category}`)
          addResult(result)
        }
      } else {
        console.log(`\n  ${category}: 未发现详情页链接`)
      }
    }

    // ====== Step 4: Generate report ======
    const report = generateReport()
    const bugsDir = path.resolve(__dirname, "..", "..", "bugs")
    fs.mkdirSync(bugsDir, { recursive: true })
    const outputPath = path.join(bugsDir, "教师端_web_test2.md")
    fs.writeFileSync(outputPath, report, "utf-8")

    console.log(`\n\n${"=".repeat(60)}`)
    const passed = allResults.filter((r) => r.status === "passed").length
    const failed = allResults.filter((r) => r.status === "failed").length
    console.log(`测试完成: 总计 ${allResults.length}, 通过 ${passed}, 失败 ${failed}`)
    console.log(`报告已写入: ${outputPath}`)
    console.log(`${"=".repeat(60)}`)
  })
})

async function testSinglePage(
  page: import("@playwright/test").Page,
  route: string,
  category: string,
): Promise<TestResult> {
  const result: TestResult = {
    url: route,
    category,
    status: "unknown",
    httpStatus: null,
    finalUrl: route,
    errors: [],
    warnings: [],
  }

  const consoleErrors: string[] = []
  const onConsole = (msg: import("@playwright/test").ConsoleMessage) => {
    if (msg.type() === "error") {
      consoleErrors.push(msg.text())
    }
  }
  page.on("console", onConsole)

  try {
    const response = await page.goto(route, { timeout: 25000 })
    await page.waitForLoadState("networkidle", { timeout: 15000 })
    await page.waitForTimeout(500)

    result.httpStatus = response?.status() ?? null
    result.finalUrl = page.url()

    const httpStatus = result.httpStatus
    const finalUrl = result.finalUrl

    if (httpStatus && httpStatus >= 500) {
      result.status = "failed"
      result.errors.push(`HTTP ${httpStatus} error`)
    } else if (httpStatus && httpStatus >= 400) {
      result.status = "warning"
      result.warnings.push(`HTTP ${httpStatus} error`)
    } else if (finalUrl.includes("/login")) {
      result.status = "failed"
      result.errors.push("Redirected to login - auth issue")
    } else if (finalUrl.includes("/error") || finalUrl.includes("/500")) {
      result.status = "failed"
      result.errors.push("Redirected to error page")
    } else {
      result.status = "passed"
    }

    // 检查页面错误提示
    const errorElements = page.locator('[role="alert"], .text-destructive, .text-red-500')
    const errorCount = await errorElements.count()
    if (errorCount > 0) {
      for (let i = 0; i < Math.min(errorCount, 3); i++) {
        const text = await errorElements.nth(i).textContent()
        if (text && text.trim()) {
          result.warnings.push(`Error text: ${text.trim().slice(0, 100)}`)
        }
      }
    }

    // 检查页面是否为空
    const bodyText = (await page.locator("body").textContent()) ?? ""
    if (bodyText.trim().length < 50) {
      result.warnings.push("Page appears empty")
    }

    if (consoleErrors.length > 0) {
      result.errors.push(...consoleErrors.slice(0, 5))
    }

    const icon = result.status === "passed" ? "✅" : result.status === "warning" ? "⚠️" : "❌"
    console.log(`    ${icon} ${result.status} (HTTP ${result.httpStatus})`)
  } catch (e) {
    result.status = "failed"
    result.errors.push(`Exception: ${String(e).slice(0, 200)}`)
    console.log(`    ❌ ERROR: ${String(e).slice(0, 100)}`)
  } finally {
    page.removeListener("console", onConsole)
  }

  return result
}

async function discoverDetailLinks(
  page: import("@playwright/test").Page,
  listRoute: string,
  linkPattern: string,
): Promise<string[]> {
  try {
    await page.goto(listRoute, { timeout: 25000 })
    await page.waitForLoadState("networkidle", { timeout: 15000 })
    await page.waitForTimeout(500)

    const links = page.locator(`a[href*="${linkPattern}"]`)
    const count = await links.count()
    const detailUrls: string[] = []

    for (let i = 0; i < Math.min(count, 3); i++) {
      const href = await links.nth(i).getAttribute("href")
      if (href && href !== listRoute && href.includes(linkPattern)) {
        detailUrls.push(href)
      }
    }
    return detailUrls
  } catch {
    return []
  }
}