import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
import { authTables } from "@convex-dev/auth/server";

// 说明：
// - 这里先按"兼容现有 Next API 返回结构"的思路设计字段：id/workspace_id/user_id 等命名保持与 Supabase 一致。
// - Convex 自带的 _id 仍然存在，但我们暂时不把它暴露给上层业务，便于逐步迁移与回退。
// - M8: 集成 Convex Auth，authTables 提供用户认证所需的数据表

export default defineSchema({
  // Convex Auth 表（用户、账户、会话等）
  ...authTables,
  workspaces: defineTable({
    id: v.string(),
    name: v.string(),
    type: v.union(v.literal("personal"), v.literal("team")),
    icon_url: v.union(v.string(), v.null()),
    created_by: v.string(),
    created_at: v.string(),
  })
    .index("by_workspace_id", ["id"])
    .index("by_created_by", ["created_by"]),

  workspace_members: defineTable({
    workspace_id: v.string(),
    user_id: v.string(),
    role: v.string(),
    is_default: v.boolean(),
    created_at: v.string(),
  })
    .index("by_user_id", ["user_id"])
    .index("by_workspace_user", ["workspace_id", "user_id"])
    .index("by_workspace_id", ["workspace_id"]),

  documents: defineTable({
    id: v.string(),
    user_id: v.string(),
    workspace_id: v.string(),

    title: v.union(v.string(), v.null()),
    parent_id: v.union(v.string(), v.null()),
    sort_order: v.union(v.number(), v.null()),
    is_starred: v.union(v.boolean(), v.null()),
    is_template: v.boolean(),
    access_scope: v.union(v.literal("private"), v.literal("shared"), v.literal("public")),

    // 页面选项（对应 Supabase documents 上的 UI 配置列）
    wide_layout: v.union(v.boolean(), v.null()),
    use_small_text: v.union(v.boolean(), v.null()),
    show_heading_numbers: v.union(v.boolean(), v.null()),
    show_toc: v.union(v.boolean(), v.null()),
    show_structure: v.union(v.boolean(), v.null()),
    protect_editing: v.union(v.boolean(), v.null()),
    show_word_count: v.union(v.boolean(), v.null()),
    collapse_backlinks: v.optional(v.union(v.boolean(), v.null())),
    page_font: v.optional(v.union(v.literal("default"), v.literal("song"), v.literal("kai"), v.null())),
    layout_density: v.optional(v.union(v.literal("compact"), v.literal("normal"), v.literal("spacious"), v.null())),
    hide_child_pages: v.optional(v.union(v.boolean(), v.null())),
    show_block_ref_count: v.optional(v.union(v.boolean(), v.null())),
    embed_default_block_id: v.optional(v.union(v.string(), v.null())),

    // 统计信息（由客户端编辑器计算后回写）
    word_count: v.union(v.number(), v.null()),
    character_count: v.union(v.number(), v.null()),
    block_count: v.union(v.number(), v.null()),
    todo_total_count: v.optional(v.union(v.number(), v.null())),
    todo_done_count: v.optional(v.union(v.number(), v.null())),

    // 说明：当前文档内容结构还在演进，先用 any 承接（与 Supabase Json 一致的宽松形态）。
    content: v.any(),
    content_revision: v.optional(v.number()),
    content_conflict_key: v.optional(v.union(v.string(), v.null())),

    // 说明：后续可用于搜索/索引（目前先留空，不强制写入）。
    raw_text: v.optional(v.union(v.string(), v.null())),

    // 时间戳统一使用 ISO 字符串，便于直接复用前端现有排序逻辑。
    created_at: v.string(),
    updated_at: v.union(v.string(), v.null()),

    // 软删除（阶段 4 先不实现垃圾桶逻辑，但字段先留好，便于后续迁移）。
    deleted_at: v.union(v.string(), v.null()),
    deleted_by: v.union(v.string(), v.null()),

    // 兼容旧逻辑：Supabase documents.mindmap_data。
    mindmap_data: v.optional(v.any()),
  })
    .index("by_document_id", ["id"])
    .index("by_user", ["user_id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_parent", ["workspace_id", "parent_id"]),

  // 最近访问（替代 Supabase user_recent_pages）
  user_recent_pages: defineTable({
    user_id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),
    last_accessed_at: v.string(),
  })
    .index("by_user_workspace", ["user_id", "workspace_id"])
    .index("by_user_document", ["user_id", "document_id"]),

  // 阶段 5：异步任务/队列表（最小骨架，后续可扩展为通用作业系统）
  jobs: defineTable({
    id: v.string(),
    user_id: v.string(),
    type: v.string(),
    status: v.union(v.literal("queued"), v.literal("running"), v.literal("succeeded"), v.literal("failed")),
    payload: v.any(),
    result: v.union(v.any(), v.null()),
    error: v.union(v.string(), v.null()),
    created_at: v.string(),
    updated_at: v.string(),
    started_at: v.union(v.string(), v.null()),
    finished_at: v.union(v.string(), v.null()),
  })
    .index("by_job_id", ["id"])
    .index("by_user", ["user_id"])
    .index("by_status", ["status"]),

  // 阶段 6：媒体/附件（替代 Supabase Storage + media_assets 表）
  media_assets: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),

    asset_type: v.string(),
    file_url: v.union(v.string(), v.null()),
    thumbnail_url: v.union(v.string(), v.null()),

    // Convex Files（storage）定位信息
    // 说明：早期阶段 6（MinIO 直存）写入的记录可能没有该字段；允许缺失以便平滑迁移。
    storage_id: v.optional(v.union(v.id("_storage"), v.null())),

    // S3/MinIO 定位信息
    bucket: v.union(v.string(), v.null()),
    storage_path: v.union(v.string(), v.null()),

    file_name: v.union(v.string(), v.null()),
    file_size: v.union(v.number(), v.null()),
    mime_type: v.union(v.string(), v.null()),

    // OCR 相关（后续再接入）
    ocr_text: v.union(v.string(), v.null()),
    ocr_status: v.union(v.string(), v.null()),
    ocr_payload: v.optional(v.any()),
    ocr_strategy: v.optional(v.union(v.string(), v.null())),

    // 回收站/清理
    deleted_at: v.union(v.string(), v.null()),
    deleted_by: v.union(v.string(), v.null()),
    purged_at: v.union(v.string(), v.null()),

    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_asset_id", ["id"])
    .index("by_storage_id", ["storage_id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_document", ["document_id"])
    .index("by_workspace_deleted", ["workspace_id", "deleted_at"]),

  // M2：思维导图（替代本地文件 public/documents/<docId>/mindmap*.json + Supabase documents.mindmap_data）
  // 说明：
  // - 业务侧依然以 (document_id, mindmap_id) 作为“定位键”，避免跨页面冲突。
  // - id 是一个便于排查的全局唯一串（例如 `${docId}:${mindmapId}`），但不要求前端依赖它。
  mindmaps: defineTable({
    id: v.string(),
    user_id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),
    mindmap_id: v.string(),
    data: v.any(),
    created_at: v.string(),
    updated_at: v.string(),
    deleted_at: v.union(v.string(), v.null()),
    deleted_by: v.union(v.string(), v.null()),
  })
    .index("by_mindmap_id", ["id"])
    .index("by_doc_mindmap", ["document_id", "mindmap_id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_deleted", ["workspace_id", "deleted_at"])
    .index("by_user", ["user_id"]),

  // M3：页面引用/反链（替代 Supabase RPC：record_page_ref、list_backlinks）
  page_references: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    source_page_id: v.string(),
    source_block_id: v.union(v.string(), v.null()),
    target_page_id: v.string(),
    alias: v.union(v.string(), v.null()),
    display_mode: v.union(v.literal("inline"), v.literal("embed")),
    is_previewable: v.boolean(),
    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_reference_id", ["id"])
    .index("by_workspace_target", ["workspace_id", "target_page_id"])
    .index("by_workspace_source", ["workspace_id", "source_page_id"])
    .index("by_unique", ["workspace_id", "source_page_id", "source_block_id", "target_page_id", "display_mode"]),

  // M5：在线表格（替代 Supabase document_tables）
  document_tables: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),
    grid_key: v.string(),
    title: v.string(),
    schema: v.any(), // TableSchema: { columns, frozenRowCount, frozenColCount }
    view_preferences: v.any(),
    snapshot: v.optional(v.any()), // DocumentTableSnapshot: { rows?, luckysheet? }
    is_archived: v.boolean(),
    // 垃圾桶字段：与附件/思维导图的删除语义保持一致（允许历史数据缺字段）
    deleted_at: v.optional(v.union(v.string(), v.null())),
    deleted_by: v.optional(v.union(v.string(), v.null())),
    purged_at: v.optional(v.union(v.string(), v.null())),
    last_synced_at: v.optional(v.string()),
    created_by: v.string(),
    updated_by: v.optional(v.string()),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_table_id", ["id"])
    .index("by_grid_key", ["grid_key"])
    .index("by_document", ["document_id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_archived", ["workspace_id", "is_archived"]),

  // M5：在线表格行数据（替代 Supabase document_table_rows）
  document_table_rows: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),
    table_id: v.string(),
    row_index: v.number(),
    row_data: v.any(),
    row_hash: v.optional(v.string()),
    is_deleted: v.boolean(),
    updated_by: v.optional(v.string()),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_row_id", ["id"])
    .index("by_table", ["table_id"])
    .index("by_table_row", ["table_id", "row_index"])
    .index("by_workspace", ["workspace_id"])
    .searchIndex("by_table_row_full", {
      searchField: "row_hash",
      filterFields: ["table_id", "is_deleted"],
    }),

  document_shares: defineTable({
    workspace_id: v.string(),
    document_id: v.string(),
    shared_with_user_id: v.string(),
    permission: v.union(v.literal("read"), v.literal("edit")),
    include_descendants: v.boolean(),
    disable_download: v.optional(v.boolean()),
    disable_copy: v.optional(v.boolean()),
    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_shared_with_user", ["shared_with_user_id"])
    .index("by_created_by", ["created_by"])
    .index("by_document", ["document_id"])
    .index("by_doc_user", ["document_id", "shared_with_user_id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_shared_with", ["workspace_id", "shared_with_user_id"])
    .index("by_workspace_created_by", ["workspace_id", "created_by"]),

  // M9：评论（页面/块）
  comment_threads: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),
    block_id: v.union(v.string(), v.null()),
    resolved_at: v.union(v.string(), v.null()),
    resolved_by: v.union(v.string(), v.null()),
    comment_count: v.number(),
    last_activity_at: v.string(),
    last_comment_preview: v.union(v.string(), v.null()),
    last_comment_by: v.union(v.string(), v.null()),
    created_by: v.string(),
    created_at: v.string(),
  })
    .index("by_thread_id", ["id"])
    .index("by_document", ["document_id"])
    .index("by_document_block", ["document_id", "block_id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_document_activity", ["workspace_id", "document_id", "last_activity_at"]),

  comment_messages: defineTable({
    id: v.string(),
    thread_id: v.string(),
    workspace_id: v.string(),
    document_id: v.string(),
    block_id: v.union(v.string(), v.null()),
    parent_id: v.union(v.string(), v.null()),
    body: v.string(),
    created_by: v.string(),
    created_at: v.string(),
    deleted_at: v.union(v.string(), v.null()),
    deleted_by: v.union(v.string(), v.null()),
  })
    .index("by_message_id", ["id"])
    .index("by_thread", ["thread_id"])
    .index("by_document", ["document_id"])
    .index("by_document_block", ["document_id", "block_id"])
    .index("by_workspace", ["workspace_id"]),

  groups: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    name: v.string(),
    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_group_id", ["id"])
    .index("by_workspace", ["workspace_id"]),

  group_members: defineTable({
    workspace_id: v.string(),
    group_id: v.string(),
    user_id: v.string(),
    role: v.union(v.literal("owner"), v.literal("member")),
    created_at: v.string(),
  })
    .index("by_group", ["group_id"])
    .index("by_group_user", ["group_id", "user_id"])
    .index("by_workspace_user", ["workspace_id", "user_id"]),

  group_invitations: defineTable({
    workspace_id: v.string(),
    group_id: v.string(),
    invited_user_id: v.string(),
    invited_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_invited_user", ["invited_user_id"])
    .index("by_group_user", ["group_id", "invited_user_id"])
    .index("by_workspace_invited_user", ["workspace_id", "invited_user_id"])
    .index("by_workspace_group", ["workspace_id", "group_id"])
    .index("by_workspace_invited_by", ["workspace_id", "invited_by"]),

  document_group_shares: defineTable({
    workspace_id: v.string(),
    group_id: v.string(),
    document_id: v.string(),
    include_descendants: v.boolean(),
    disable_download: v.optional(v.boolean()),
    disable_copy: v.optional(v.boolean()),
    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_document", ["document_id"])
    .index("by_doc_group", ["document_id", "group_id"])
    .index("by_workspace_group", ["workspace_id", "group_id"])
    .index("by_workspace_created_by", ["workspace_id", "created_by"]),

  document_group_user_permissions: defineTable({
    workspace_id: v.string(),
    group_id: v.string(),
    document_id: v.string(),
    user_id: v.string(),
    permission: v.union(v.literal("read"), v.literal("edit")),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_doc_group_user", ["document_id", "group_id", "user_id"])
    .index("by_workspace_user", ["workspace_id", "user_id"])
    .index("by_workspace_group", ["workspace_id", "group_id"]),

  document_stars: defineTable({
    workspace_id: v.string(),
    document_id: v.string(),
    user_id: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_workspace_user", ["workspace_id", "user_id"])
    .index("by_user_document", ["user_id", "document_id"])
    .index("by_workspace_document_user", ["workspace_id", "document_id", "user_id"]),

  // === 新领域模型表（Action Execution System）===

  // Pages 表 - 对应域模型 Page
  pages: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    parent_id: v.union(v.string(), v.null()),
    title: v.string(),
    access_scope: v.union(v.literal("private"), v.literal("shared"), v.literal("public")),
    block_ids: v.array(v.string()),
    child_page_ids: v.array(v.string()),
    asset_ids: v.array(v.string()),
    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
    deleted_at: v.union(v.string(), v.null()),
  })
    .index("by_page_id", ["id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_parent", ["workspace_id", "parent_id"])
    .index("by_workspace_deleted", ["workspace_id", "deleted_at"]),

  // Blocks 表 - 对应域模型 Block
  blocks: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    page_id: v.string(),
    parent_block_id: v.union(v.string(), v.null()),
    type: v.string(),
    props: v.optional(v.any()),
    content: v.optional(v.any()),
    child_block_ids: v.array(v.string()),
    created_by: v.string(),
    created_at: v.string(),
    updated_at: v.string(),
  })
    .index("by_block_id", ["id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_page", ["page_id"])
    .index("by_page_parent", ["page_id", "parent_block_id"]),

  // Agent Actions 表 - 对应域模型 AgentAction（持久化日志）
  agent_actions: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    session_id: v.string(),
    action_type: v.string(),
    status: v.union(v.literal("planned"), v.literal("running"), v.literal("succeeded"), v.literal("failed"), v.literal("cancelled")),
    actor: v.union(v.literal("human"), v.literal("agent"), v.literal("automation")),
    input: v.any(),
    output: v.optional(v.any()),
    error: v.optional(v.string()),
    started_at: v.string(),
    finished_at: v.optional(v.string()),
  })
    .index("by_action_id", ["id"])
    .index("by_workspace", ["workspace_id"])
    .index("by_workspace_session", ["workspace_id", "session_id"])
    .index("by_session", ["session_id"])
    .index("by_workspace_status", ["workspace_id", "status"]),

  command_logs: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    request_id: v.string(),
    trace_id: v.string(),
    command_id: v.string(),
    command_name: v.string(),
    actor_id: v.string(),
    actor_type: v.string(),
    source_channel: v.string(),
    source_client: v.string(),
    status: v.union(v.literal("pending"), v.literal("succeeded"), v.literal("failed"), v.literal("rolled_back")),
    target_page_id: v.optional(v.union(v.string(), v.null())),
    target_block_id: v.optional(v.union(v.string(), v.null())),
    payload: v.any(),
    payload_summary: v.string(),
    refs: v.array(v.string()),
    idempotency_key: v.optional(v.union(v.string(), v.null())),
    error: v.optional(v.union(v.string(), v.null())),
    created_at: v.string(),
    finished_at: v.optional(v.union(v.string(), v.null())),
  })
    .index("by_command_log_id", ["id"])
    .index("by_workspace_request", ["workspace_id", "request_id"])
    .index("by_workspace_trace", ["workspace_id", "trace_id"])
    .index("by_workspace_command", ["workspace_id", "command_id"]),

  domain_events: defineTable({
    id: v.string(),
    workspace_id: v.string(),
    request_id: v.string(),
    trace_id: v.string(),
    command_id: v.string(),
    command_log_id: v.string(),
    event_type: v.string(),
    aggregate_type: v.string(),
    aggregate_id: v.string(),
    event_version: v.number(),
    status: v.union(v.literal("pending"), v.literal("committed"), v.literal("rejected"), v.literal("failed")),
    actor_type: v.string(),
    payload: v.any(),
    created_at: v.string(),
  })
    .index("by_domain_event_id", ["id"])
    .index("by_workspace_request", ["workspace_id", "request_id"])
    .index("by_workspace_trace", ["workspace_id", "trace_id"])
    .index("by_workspace_command", ["workspace_id", "command_id"]),
});
