"use client";

/**
 * LocalMessage 模型（存储层副本）
 *
 * 与 `src/data/models/chat/chat_message.ts` 的 `ChatMessage` 解耦：
 * 存储层维护自己的数据形态（独立 id/role/content/createdAt + 内部 sessionId 分组），
 * 不耦合 wire 模型，方便后续 schema 独立演进。
 *
 * 对齐项目内其他 Zod 模型的范式：
 *   - `*Schema` 是验证与默认值的单一来源
 *   - `*Input` 是构造输入（字段可缺），`*Data` 是解析后形态
 *   - 不可变（private constructor + Object.freeze）
 *   - 桥接方法 `toRow` / `fromRow` 处理 Dexie 行 ↔ 类实例的转换
 */

import { z } from "zod";
import { ChatImageSchema, ChatLockDetailSchema } from "@/data/schemas/chat";
import type { LocalMessageRow } from "./local_chat_db";

export const LocalMessageSchema = z.object({
  id: z.string(),
  role: z.string(),
  type: z.string().default("text"),
  content: z.string(),
  createdAt: z.string().default(""),
  audioUrl: z.string().nullable().default(null),
  image: ChatImageSchema,
  lockDetail: ChatLockDetailSchema,
  sessionId: z.string().default(""),
});

export type LocalMessageInput = z.input<typeof LocalMessageSchema>;
export type LocalMessageData = z.output<typeof LocalMessageSchema>;

export class LocalMessage {
  declare readonly id: string;
  declare readonly role: string;
  declare readonly type: string;
  declare readonly content: string;
  declare readonly createdAt: string;
  declare readonly audioUrl: string | null;
  declare readonly image: z.output<typeof ChatImageSchema>;
  declare readonly lockDetail: z.output<typeof ChatLockDetailSchema>;
  declare readonly sessionId: string;

  private constructor(input: LocalMessageInput) {
    const data = LocalMessageSchema.parse(input);
    Object.assign(this, data);
    Object.freeze(this);
  }

  static from(input: LocalMessageInput): LocalMessage {
    return new LocalMessage(input);
  }

  static fromJson(json: unknown): LocalMessage {
    return LocalMessage.from(json as LocalMessageInput);
  }

  toJson(): LocalMessageData {
    return LocalMessageSchema.parse(this);
  }

  /** 转成 Dexie 行（不含 dbId，让 Dexie 自增）。 */
  toRow(): Omit<LocalMessageRow, "dbId"> {
    return {
      id: this.id,
      role: this.role,
      type: this.type,
      content: this.content,
      createdAt: this.createdAt,
      audioUrl: this.audioUrl,
      image: this.image,
      lockDetail: this.lockDetail,
      sessionId: this.sessionId,
    };
  }

  /** 从 Dexie 行还原（忽略 dbId 内部主键）。 */
  static fromRow(row: LocalMessageRow): LocalMessage {
    return LocalMessage.from({
      id: row.id,
      role: row.role,
      type: row.type,
      content: row.content,
      createdAt: row.createdAt,
      audioUrl: row.audioUrl ?? null,
      image: row.image,
      lockDetail: row.lockDetail,
      sessionId: row.sessionId,
    });
  }
}
