import { describe, expect, it } from "vitest"

import { isAnnouncementVisibleToAudience } from "./data-access"
import type { UserAudience } from "./types"

/**
 * P2-7: `isAnnouncementVisibleToAudience` 纯函数单元测试。
 *
 * 此函数无 DB 依赖（不读取 data-access.ts 顶部的 `import "server-only"` 副作用字段），
 * 但因 `data-access.ts` 顶部声明 `import "server-only"`，需在 vitest config 中
 * 已将 `server-only` 映射为空模块方可运行（项目已配置，见 vitest.config.ts）。
 *
 * 覆盖矩阵：
 * - audience=null（管理员视角）：所有类型公告均可见
 * - school 类型：对所有 audience 可见（即便 audience 为空）
 * - grade 类型：targetGradeId ∈ audience.gradeIds 时可见
 * - class 类型：targetClassId ∈ audience.classIds 时可见
 * - 边界：targetGradeId/targetClassId 为 null 时不可见（除 school 外）
 * - 多孩子/多班级场景：数组中任一匹配即可见
 */
describe("isAnnouncementVisibleToAudience", () => {
  const schoolAnnouncement = {
    type: "school" as const,
    targetGradeId: null,
    targetClassId: null,
  }

  const gradeAnnouncement = {
    type: "grade" as const,
    targetGradeId: "grade-1",
    targetClassId: null,
  }

  const classAnnouncement = {
    type: "class" as const,
    targetGradeId: null,
    targetClassId: "class-1",
  }

  describe("audience=null（管理员视角）", () => {
    it("school 公告可见", () => {
      expect(isAnnouncementVisibleToAudience(schoolAnnouncement, null)).toBe(true)
    })

    it("grade 公告可见", () => {
      expect(isAnnouncementVisibleToAudience(gradeAnnouncement, null)).toBe(true)
    })

    it("class 公告可见", () => {
      expect(isAnnouncementVisibleToAudience(classAnnouncement, null)).toBe(true)
    })
  })

  describe("school 类型公告", () => {
    it("对空 audience 可见", () => {
      const emptyAudience: UserAudience = { gradeIds: [], classIds: [] }
      expect(isAnnouncementVisibleToAudience(schoolAnnouncement, emptyAudience)).toBe(true)
    })

    it("对任意 audience 可见", () => {
      const audience: UserAudience = { gradeIds: ["grade-99"], classIds: ["class-99"] }
      expect(isAnnouncementVisibleToAudience(schoolAnnouncement, audience)).toBe(true)
    })
  })

  describe("grade 类型公告", () => {
    it("targetGradeId ∈ audience.gradeIds：可见", () => {
      const audience: UserAudience = { gradeIds: ["grade-1", "grade-2"], classIds: [] }
      expect(isAnnouncementVisibleToAudience(gradeAnnouncement, audience)).toBe(true)
    })

    it("targetGradeId ∉ audience.gradeIds：不可见", () => {
      const audience: UserAudience = { gradeIds: ["grade-2", "grade-3"], classIds: [] }
      expect(isAnnouncementVisibleToAudience(gradeAnnouncement, audience)).toBe(false)
    })

    it("audience.gradeIds 为空：不可见", () => {
      const audience: UserAudience = { gradeIds: [], classIds: [] }
      expect(isAnnouncementVisibleToAudience(gradeAnnouncement, audience)).toBe(false)
    })

    it("targetGradeId 为 null：不可见（数据完整性问题）", () => {
      const invalidGradeAnnouncement = {
        type: "grade" as const,
        targetGradeId: null,
        targetClassId: null,
      }
      const audience: UserAudience = { gradeIds: ["grade-1"], classIds: [] }
      expect(isAnnouncementVisibleToAudience(invalidGradeAnnouncement, audience)).toBe(false)
    })

    it("P0-2 多孩子场景：年级在 audience 中即可见", () => {
      // 家长有两个孩子分别在不同年级
      const audience: UserAudience = { gradeIds: ["grade-5", "grade-6"], classIds: [] }
      const grade5Announcement = {
        type: "grade" as const,
        targetGradeId: "grade-5",
        targetClassId: null,
      }
      const grade6Announcement = {
        type: "grade" as const,
        targetGradeId: "grade-6",
        targetClassId: null,
      }
      expect(isAnnouncementVisibleToAudience(grade5Announcement, audience)).toBe(true)
      expect(isAnnouncementVisibleToAudience(grade6Announcement, audience)).toBe(true)
    })
  })

  describe("class 类型公告", () => {
    it("targetClassId ∈ audience.classIds：可见", () => {
      const audience: UserAudience = { gradeIds: [], classIds: ["class-1", "class-2"] }
      expect(isAnnouncementVisibleToAudience(classAnnouncement, audience)).toBe(true)
    })

    it("targetClassId ∉ audience.classIds：不可见", () => {
      const audience: UserAudience = { gradeIds: [], classIds: ["class-2", "class-3"] }
      expect(isAnnouncementVisibleToAudience(classAnnouncement, audience)).toBe(false)
    })

    it("audience.classIds 为空：不可见", () => {
      const audience: UserAudience = { gradeIds: [], classIds: [] }
      expect(isAnnouncementVisibleToAudience(classAnnouncement, audience)).toBe(false)
    })

    it("targetClassId 为 null：不可见", () => {
      const invalidClassAnnouncement = {
        type: "class" as const,
        targetGradeId: null,
        targetClassId: null,
      }
      const audience: UserAudience = { gradeIds: [], classIds: ["class-1"] }
      expect(isAnnouncementVisibleToAudience(invalidClassAnnouncement, audience)).toBe(false)
    })

    it("P0-2 教师多班级场景：班级在 audience 中即可见", () => {
      // 教师同时任教两个班级
      const audience: UserAudience = { gradeIds: [], classIds: ["class-a", "class-b"] }
      const classAAnnouncement = {
        type: "class" as const,
        targetGradeId: null,
        targetClassId: "class-a",
      }
      const classBAnnouncement = {
        type: "class" as const,
        targetGradeId: null,
        targetClassId: "class-b",
      }
      expect(isAnnouncementVisibleToAudience(classAAnnouncement, audience)).toBe(true)
      expect(isAnnouncementVisibleToAudience(classBAnnouncement, audience)).toBe(true)
    })
  })
})
