// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
    provider = "prisma-client-js"
}

datasource db {
    provider = "postgresql"
    url      = env("DATABASE_URL")
}

model Taxonomy {
    id         String    @id @default(cuid())
    name       String    @unique
    slug       String    @unique @map("slug")
    deletedAt  DateTime? @map("deleted_at")
    createdAt  DateTime  @default(now()) @map("created_at")
    terms      Term[]
    objectType String[]  @map("object_type")
    order      Float?    @map("order")

    @@index([order, deletedAt])
    @@map("taxonomy")
}

model Term {
    id          String         @id @default(cuid())
    name        String
    taxonomy    Taxonomy?      @relation(fields: [taxonomyId], references: [id])
    taxonomyId  String?        @map("taxonomy_id")
    order       Float?         @map("order")
    description String?
    parentId    String?        @map("parent_id")
    parent      Term?          @relation("ChildParent", fields: [parentId], references: [id], onDelete: Cascade)
    children    Term[]         @relation("ChildParent")
    ancestors   TermAncestry[] @relation("DescendantToAncestor")
    descendants TermAncestry[] @relation("AncestorToDescendant")
    domainId    String?        @map("domain_id")
    domain      Department?    @relation("TermDom", fields: [domainId], references: [id])
    createdAt   DateTime       @default(now()) @map("created_at")
    updatedAt   DateTime       @updatedAt @map("updated_at")
    deletedAt   DateTime?      @map("deleted_at")
    createdBy   String?        @map("created_by")
    depts       Department[]   @relation("department_term")
    hasChildren Boolean?       @default(false) @map("has_children")
    courses     Course[]       @relation("course_term")

    @@index([name]) // 对name字段建立索引，以加快基于name的查找速度
    @@index([parentId]) // 对parentId字段建立索引，以加快基于parentId的查找速度
    @@map("term")
}

model TermAncestry {
    id           String  @id @default(cuid())
    ancestorId   String? @map("ancestor_id")
    descendantId String  @map("descendant_id")
    relDepth     Int     @map("rel_depth")
    ancestor     Term?   @relation("AncestorToDescendant", fields: [ancestorId], references: [id])
    descendant   Term    @relation("DescendantToAncestor", fields: [descendantId], references: [id])

    // 索引建议
    @@index([ancestorId]) // 针对祖先的查询
    @@index([descendantId]) // 针对后代的查询
    @@index([ancestorId, descendantId]) // 组合索引，用于查询特定的祖先-后代关系
    @@index([relDepth]) // 根据关系深度的查询
    @@map("term_ancestry")
}

model Staff {
    id          String  @id @default(cuid())
    showname    String? @map("showname")
    username    String  @unique @map("username")
    avatar      String? @map("avatar")
    password    String? @map("password")
    phoneNumber String? @unique @map("phone_number")

    domainId String? @map("domain_id")
    deptId   String? @map("dept_id")

    domain     Department? @relation("DomainStaff", fields: [domainId], references: [id])
    department Department? @relation("DeptStaff", fields: [deptId], references: [id])
    order      Float?

    createdAt DateTime  @default(now()) @map("created_at")
    updatedAt DateTime  @updatedAt @map("updated_at")
    enabled   Boolean?  @default(true)
    deletedAt DateTime? @map("deleted_at")
    officerId String?   @map("officer_id")

    watchedPost    Post[]             @relation("post_watch_staff")
    visits         Visit[]
    posts          Post[]
    sentMsgs       Message[]          @relation("message_sender")
    receivedMsgs   Message[]          @relation("message_receiver")
    registerToken  String?
    enrollments    Enrollment[]
    teachedCourses CourseInstructor[]
    ownedResources Resource[]

    @@index([officerId])
    @@index([deptId])
    @@index([domainId])
    @@index([username])
    @@index([order])
    @@map("staff")
}

model Department {
    id           String         @id @default(cuid())
    name         String
    order        Float?
    ancestors    DeptAncestry[] @relation("DescendantToAncestor")
    descendants  DeptAncestry[] @relation("AncestorToDescendant")
    parentId     String?        @map("parent_id")
    parent       Department?    @relation("ChildParent", fields: [parentId], references: [id])
    children     Department[]   @relation("ChildParent")
    domainId     String?        @map("domain_id")
    domainTerms  Term[]         @relation("TermDom")
    deletedAt    DateTime?      @map("deleted_at")
    isDomain     Boolean?       @default(false) @map("is_domain")
    domainStaffs Staff[]        @relation("DomainStaff")
    deptStaffs   Staff[]        @relation("DeptStaff")
    terms        Term[]         @relation("department_term")

    watchedPost Post[]   @relation("post_watch_dept")
    hasChildren Boolean? @default(false) @map("has_children")

    @@index([parentId])
    @@index([isDomain])
    @@index([name])
    @@index([order])
    @@map("department")
}

model DeptAncestry {
    id           String      @id @default(cuid())
    ancestorId   String?     @map("ancestor_id")
    descendantId String      @map("descendant_id")
    relDepth     Int         @map("rel_depth")
    ancestor     Department? @relation("AncestorToDescendant", fields: [ancestorId], references: [id])
    descendant   Department  @relation("DescendantToAncestor", fields: [descendantId], references: [id])

    // 索引建议
    @@index([ancestorId]) // 针对祖先的查询
    @@index([descendantId]) // 针对后代的查询
    @@index([ancestorId, descendantId]) // 组合索引，用于查询特定的祖先-后代关系
    @@index([relDepth]) // 根据关系深度的查询
    @@map("dept_ancestry")
}

model RoleMap {
    id         String  @id @default(cuid())
    objectId   String  @map("object_id")
    roleId     String  @map("role_id")
    domainId   String? @map("domain_id")
    objectType String  @map("object_type")
    role       Role    @relation(fields: [roleId], references: [id])

    @@index([domainId])
    @@index([objectId])
    @@map("rolemap")
}

model Role {
    id          String    @id @default(cuid())
    name        String    @unique @map("name")
    permissions String[]  @default([]) @map("permissions")
    roleMaps    RoleMap[]
    system      Boolean?  @default(false) @map("system")
    createdAt   DateTime  @default(now()) @map("created_at")
    updatedAt   DateTime  @updatedAt @map("updated_at")
    deletedAt   DateTime? @map("deleted_at")

    @@map("role")
}

model AppConfig {
    id          String  @id @default(cuid())
    slug        String  @unique
    title       String?
    description String?
    meta        Json?

    @@map("app_config")
}

model Post {
    // 字符串类型字段
    id        String    @id @default(cuid()) // 帖子唯一标识，使用 cuid() 生成默认值
    type      String? // 帖子类型，可为空
    title     String? // 帖子标题，可为空
    content   String? // 帖子内容，可为空
    domainId  String?   @map("domain_id")
    // 日期时间类型字段
    createdAt DateTime  @default(now()) @map("created_at")
    updatedAt DateTime  @updatedAt @map("updated_at")
    deletedAt DateTime? @map("deleted_at") // 删除时间，可为空
    // 整数类型字段
    rating    Int // 评分(1-5星)
    // 关系类型字段
    authorId  String?   @map("author_id")
    author    Staff?    @relation(fields: [authorId], references: [id]) // 帖子作者，关联 Staff 模型

    visits Visit[] // 访问记录，关联 Visit 模型

    courseId String @map("course_id")
    course   Course @relation(fields: [courseId], references: [id]) // 关联课程，关联 Course 模型

    parentId String? @map("parent_id")
    parent   Post?   @relation("PostChildren", fields: [parentId], references: [id]) // 父级帖子，关联 Post 模型
    children Post[]  @relation("PostChildren") // 子级帖子列表，关联 Post 模型

    lectureId String?    @map("lecture_id")
    lecture   Lecture?   @relation(fields: [lectureId], references: [id]) // 关联讲座，关联 Lecture 模型
    resources Resource[] // 附件列表

    watchableStaffs Staff[]      @relation("post_watch_staff") // 可观看的员工列表，关联 Staff 模型
    watchableDepts  Department[] @relation("post_watch_dept") // 可观看的部门列表，关联 Department 模型

    // 复合索引
    @@index([type, domainId]) // 类型和域组合查询
    @@index([authorId, type]) // 作者和类型组合查询
    @@index([parentId, type]) // 父级帖子和创建时间索引
    // 时间相关索引
    @@index([createdAt]) // 按创建时间倒序索引
    @@index([updatedAt]) // 按更新时间倒序索引
}

model Message {
    id        String    @id @default(cuid())
    url       String?
    intent    String?
    option    Json?
    senderId  String?   @map("sender_id")
    type      String?
    sender    Staff?    @relation(name: "message_sender", fields: [senderId], references: [id])
    title     String?
    content   String?
    receivers Staff[]   @relation("message_receiver")
    visits    Visit[]
    createdAt DateTime  @default(now()) @map("created_at")
    updatedAt DateTime? @updatedAt @map("updated_at")

    @@index([type, createdAt])
    @@map("message")
}

model Visit {
    id        String   @id @default(cuid()) @map("id")
    type      String?
    views     Int      @default(1) @map("views")
    // sourceIP  String?  @map("source_ip")
    // 关联关系
    visitorId String   @map("visitor_id")
    visitor   Staff    @relation(fields: [visitorId], references: [id])
    postId    String?  @map("post_id")
    post      Post?    @relation(fields: [postId], references: [id])
    message   Message? @relation(fields: [messageId], references: [id])
    messageId String?  @map("message_id")
    lecture   Lecture? @relation(fields: [lectureId], references: [id], onDelete: Cascade)
    lectureId String?  @map("lecture_id") // 课时ID

    // 学习数据
    // progress       Float?    @default(0) @map("progress") // 完成进度(0-100%)
    // isCompleted    Boolean?  @default(false) @map("is_completed") // 是否完成
    // lastPosition   Int?      @default(0) @map("last_position") // 视频播放位置(秒)
    // totalWatchTime Int?      @default(0) @map("total_watch_time") // 总观看时长(秒)
    // // 时间记录
    // lastWatchedAt  DateTime? @map("last_watched_at") // 最后观看时间
    createdAt DateTime @default(now()) @map("created_at") // 创建时间
    updatedAt DateTime @updatedAt @map("updated_at") // 更新时间

    meta Json?

    @@index([postId, type, visitorId])
    @@index([messageId, type, visitorId])
    @@map("visit")
}

model Course {
    id           String             @id @default(cuid()) @map("id") // 课程唯一标识符
    title        String?            @map("title") // 课程标题
    subTitle     String?            @map("sub_title") // 课程副标题(可选)
    description  String?            @map("description") // 课程详细描述 
    thumbnail    String?            @map("thumbnail") // 课程封面图片URL(可选)
    level        String?            @map("level") // 课程难度等级
    // 课程内容组织结构
    terms        Term[]             @relation("course_term") // 课程学期
    instructors  CourseInstructor[] // 课程讲师团队
    sections     Section[] // 课程章节结构
    lectures     Lecture[]
    enrollments  Enrollment[] // 学生报名记录
    reviews      Post[] // 学员课程评价
    // 课程规划与目标设定
    requirements String[]           @map("requirements") // 课程学习前置要求
    objectives   String[]           @map("objectives") // 具体的学习目标
    // 课程状态管理
    status       String?            @map("status") // 课程状态(如:草稿/已发布/已归档)
    featured     Boolean?           @default(false) @map("featured") // 是否为精选推荐课程

    // 生命周期时间戳
    createdAt   DateTime? @default(now()) @map("created_at") // 创建时间
    updatedAt   DateTime? @updatedAt @map("updated_at") // 最后更新时间
    publishedAt DateTime? @map("published_at") // 发布时间
    deletedAt   DateTime? @map("deleted_at") // 软删除时间
    meta        Json?

    // 课程统计指标
    // totalDuration    Int?   @default(0) @map("total_duration") // 课程总时长(分钟)
    // totalLectures    Int?   @default(0) @map("total_lectures") // 总课时数
    // averageRating    Float? @default(0) @map("average_rating") // 平均评分(1-5分)
    // numberOfReviews  Int?   @default(0) @map("number_of_reviews") // 评价总数
    // numberOfStudents Int?   @default(0) @map("number_of_students") // 学习人数
    // completionRate   Float? @default(0) @map("completion_rate") // 完课率(0-100%)
    // 数据库索引优化
    @@index([status]) // 课程状态索引,用于快速筛选
    @@index([level]) // 难度等级索引,用于分类查询
    @@index([featured]) // 精选标记索引,用于首页推荐
    @@map("course")
}

model Section {
    id          String   @id @default(cuid()) @map("id")
    title       String   @map("title")
    description String?  @map("description")
    objectives  String[] @map("objectives")
    order       Float?   @default(0) @map("order")

    createdAt DateTime  @default(now()) @map("created_at")
    updatedAt DateTime  @updatedAt @map("updated_at")
    deletedAt DateTime? @map("deleted_at")
    // 关联关系
    course    Course    @relation(fields: [courseId], references: [id], onDelete: Cascade)
    courseId  String    @map("course_id")
    lectures  Lecture[]
    meta      Json?

    //   totalDuration Int       @default(0) @map("total_duration")
    // totalLectures Int       @default(0) @map("total_lectures")
    @@index([courseId, order])
    @@map("section")
}

model Lecture {
    id          String  @id @default(cuid()) @map("id")
    title       String  @map("title")
    description String? @map("description")
    content     String? @map("content")
    order       Float?  @default(0) @map("order")
    duration    Int     @map("duration")
    type        String  @map("type")

    videoUrl       String?    @map("video_url")
    videoThumbnail String?    @map("video_thumbnail")
    publishedAt    DateTime?  @map("published_at")
    createdAt      DateTime   @default(now()) @map("created_at")
    updatedAt      DateTime   @updatedAt @map("updated_at")
    deletedAt      DateTime?  @map("deleted_at")
    // 关联关系
    resources      Resource[]
    section        Section?   @relation(fields: [sectionId], references: [id], onDelete: Cascade)
    sectionId      String?    @map("section_id")
    course         Course?    @relation(fields: [courseId], references: [id], onDelete: Cascade)
    courseId       String?    @map("course_id")
    comments       Post[]
    visits         Visit[]

    @@index([sectionId, order])
    @@index([type, publishedAt])
    @@map("lecture")
}

model Enrollment {
    id             String @id @default(cuid()) @map("id")
    status         String @map("status")
    completionRate Float  @default(0) @map("completion_rate")

    createdAt   DateTime  @default(now()) @map("created_at")
    updatedAt   DateTime  @updatedAt @map("updated_at")
    completedAt DateTime? @map("completed_at")

    // 关联关系
    student   Staff  @relation(fields: [studentId], references: [id])
    studentId String @map("student_id")
    course    Course @relation(fields: [courseId], references: [id])
    courseId  String @map("course_id")

    @@unique([studentId, courseId])
    @@index([status])
    @@index([completedAt])
    @@map("enrollment")
}

model CourseInstructor {
    courseId     String   @map("course_id")
    instructorId String   @map("instructor_id")
    role         String   @map("role")
    createdAt    DateTime @default(now()) @map("created_at")
    order        Float?   @default(0) @map("order")

    course     Course @relation(fields: [courseId], references: [id])
    instructor Staff  @relation(fields: [instructorId], references: [id])

    @@id([courseId, instructorId])
    @@map("course_instructor")
}

model Resource {
    id          String    @id @default(cuid()) @map("id")
    title       String?   @map("title")
    description String?   @map("description")
    type        String?   @map("type")
    fileId      String?   @unique
    url         String?
    // 元数据
    metadata    Json?     @map("metadata")
    // 处理状态控制
    status      String?
    createdAt   DateTime? @default(now()) @map("created_at")
    updatedAt   DateTime? @updatedAt @map("updated_at")
    createdBy   String?   @map("created_by")
    updatedBy   String?   @map("updated_by")
    deletedAt   DateTime? @map("deleted_at")
    isPublic    Boolean?  @default(true) @map("is_public")
    owner       Staff?    @relation(fields: [ownerId], references: [id])
    ownerId     String?   @map("owner_id")
    post        Post?     @relation(fields: [postId], references: [id])
    postId      String?   @map("post_id")
    lecture     Lecture?  @relation(fields: [lectureId], references: [id])
    lectureId   String?   @map("lecture_id")

    // 索引
    @@index([type])
    @@index([createdAt])
    @@map("resource")
}

model Node {
    id          String   @id @default(cuid()) @map("id")
    title       String   @map("title")
    description String?  @map("description")
    type        String   @map("type")
    style       Json?    @map("style")
    position    Json?    @map("position")
    data        Json?    @map("data")
    createdAt   DateTime @default(now()) @map("created_at")
    updatedAt   DateTime @updatedAt @map("updated_at")

    // 关联关系
    sourceEdges NodeEdge[] @relation("source_node")
    targetEdges NodeEdge[] @relation("target_node")

    @@map("node")
}

model NodeEdge {
    id          String   @id @default(cuid()) @map("id")
    type        String?  @map("type")
    label       String?  @map("label")
    description String?  @map("description")
    style       Json?    @map("style")
    createdAt   DateTime @default(now()) @map("created_at")
    updatedAt   DateTime @updatedAt @map("updated_at")

    source   Node   @relation("source_node", fields: [sourceId], references: [id], onDelete: Cascade)
    sourceId String @map("source_id")
    target   Node   @relation("target_node", fields: [targetId], references: [id], onDelete: Cascade)
    targetId String @map("target_id")

    @@unique([sourceId, targetId, type])
    @@index([sourceId])
    @@index([targetId])
    @@map("node_edge")
}
