"use client";

/**
 * Dexie 数据库定义
 *
 * `messages.sessionId` 是当前聊天身份的缓存命名空间。所有消息读写必须通过
 * 该索引限定身份，不能退化为整表操作。
 *
 * 构造时 `dbName` 可注入，便于测试时每个用例用独立 DB 互不污染。
 */

import Dexie, { type Table } from "dexie";
import type { ChatMediaKind } from "@/data/dto/chat";
import type {
  ChatImageData,
  ChatLockDetailData,
} from "@/data/schemas/chat";

export interface LocalMessageRow {
  /** Dexie 自增主键（数据库内部使用，不暴露给 LocalMessage 类）。 */
  dbId?: number;
  /** 消息 id（来自 ChatMessage.id）。 */
  id: string;
  role: string;
  type: string;
  content: string;
  createdAt: string;
  audioUrl?: string | null;
  image?: ChatImageData;
  lockDetail?: ChatLockDetailData;
  sessionId: string;
}

export interface LocalChatMediaRow {
  cacheKey: string;
  ownerKey: string;
  messageId: string;
  kind: ChatMediaKind;
  remoteUrl: string;
  /** v3+ stores raw bytes instead of Blob to avoid iOS WebKit Blob URL issues. */
  bytes?: ArrayBuffer;
  /** Legacy v2 field. Read-only fallback for users who already have cached media. */
  blob?: Blob;
  mimeType: string;
  byteSize: number;
  createdAt: number;
  updatedAt: number;
  lastAccessedAt: number;
}

export class LocalChatDB extends Dexie {
  messages!: Table<LocalMessageRow, number>;
  media!: Table<LocalChatMediaRow, string>;

  constructor(dbName: string = "cozsweet-chat") {
    super(dbName);
    this.version(1).stores({
      messages: "++dbId",
    });
    this.version(2).stores({
      messages: "++dbId",
      media: "cacheKey, ownerKey, messageId, kind, remoteUrl, updatedAt, lastAccessedAt",
    });
    this.version(3)
      .stores({
        messages: "++dbId, sessionId",
        media: "cacheKey, ownerKey, messageId, kind, remoteUrl, updatedAt, lastAccessedAt",
      })
      .upgrade(async (transaction) => {
        // v1/v2 always wrote an empty sessionId. Its owner cannot be recovered,
        // so retaining it would expose one identity's history to another.
        await transaction.table("messages").clear();
      });
  }
}
