"use client";

/**
 * ChatRepository
 *
 * 聊天仓库：编排远程 ChatApi + 本地 LocalChatStorage（Dexie/IndexedDB）。
 * 行为对齐原 Dart `lib/data/repositories/chat_repository_impl.dart`：
 *   - `saveMessagesToLocal` 保留「先清后写」语义（Dart `box.clear()` + bulk add）
 *   - 替代 Dart 同步 `int get localMessageCount`，改为异步 `getLocalMessageCount()`
 *     （Dexie 异步 API 决定）
 *
 * ChatMessage ↔ LocalMessage 的字段映射在仓库内 inline 完成（用户决策）：
 *   - 写：ChatMessage 的 id/role/content/createdAt → LocalMessage（sessionId=""）
 *   - 读：LocalMessage 的 id/role/content/createdAt → ChatMessage（丢弃 sessionId）
 *
 * 原始 Dart: lib/data/repositories/chat_repository_impl.dart
 */
import { ChatApi, chatApi } from "@/data/services/api";
import {
  ChatHistoryResponse,
  ChatMessage,
  ChatSendResponse,
  SendMessageRequest,
  UnlockPrivateRequest,
  UnlockPrivateResponse,
} from "@/data/dto/chat";
import { Result } from "@/utils";
import type { IChatRepository } from "@/data/repositories/interfaces";
import { LocalChatStorage, LocalMessage } from "@/data/storage/chat";

export class ChatRepository implements IChatRepository {
  constructor(
    private readonly api: ChatApi,
    private readonly localStorage: LocalChatStorage,
  ) {}

  // ============ 远程操作 ============

  /** 发送一条消息。 */
  async sendMessage(
    message: string,
    options?: { image?: string; useWebSocket?: boolean },
  ): Promise<Result<ChatSendResponse>> {
    return Result.wrap(async () => {
      const request = SendMessageRequest.from({
        message,
        image: options?.image ?? "",
        useWebSocket: options?.useWebSocket ?? false,
      });
      return await this.api.sendMessage(request);
    });
  }

  /** 获取聊天历史，分页参数默认 limit=50, offset=0。 */
  async getHistory(
    limit = 50,
    offset = 0,
  ): Promise<Result<ChatHistoryResponse>> {
    return Result.wrap(() => this.api.getHistory(limit, offset));
  }

  /** 解锁私密消息。 */
  async unlockPrivateMessage(
    messageId: string,
  ): Promise<Result<UnlockPrivateResponse>> {
    return Result.wrap(() =>
      this.api.unlockPrivateMessage(UnlockPrivateRequest.from({ messageId })),
    );
  }

  // ============ 本地（Dexie）操作 ============

  /** 把一条消息写入本地存储。 */
  async saveMessageToLocal(message: ChatMessage): Promise<Result<void>> {
    return this._mapLocalStorageResult(
      this.localStorage.saveMessage(this._chatToLocal(message)),
    );
  }

  /**
   * 批量覆盖写入：先清空本地存储，再写入新列表。
   * 保留 Dart 端的「先清后写」语义（用于同步场景的整批刷新）。
   */
  async saveMessagesToLocal(
    messages: readonly ChatMessage[],
  ): Promise<Result<void>> {
    const cleared = await this.localStorage.clearAll();
    if (!cleared.success) {
      return Result.err(cleared.error);
    }
    return this._mapLocalStorageResult(
      this.localStorage.saveMessages(messages.map((m) => this._chatToLocal(m))),
    );
  }

  /** 读取所有本地消息，按 dbId 升序。 */
  async getLocalMessages(): Promise<Result<ChatMessage[]>> {
    const result = await this.localStorage.getAllMessages();
    if (!result.success) {
      return Result.err(result.error);
    }
    return Result.ok(result.data.map((lm) => this._localToChat(lm)));
  }

  /** 清空本地消息。 */
  async clearLocalMessages(): Promise<Result<void>> {
    return this._mapLocalStorageResult(this.localStorage.clearAll());
  }

  /**
   * 获取本地消息数量。
   * 替代 Dart 的同步 `int get localMessageCount`——Dexie 异步 API 决定必须 async。
   */
  async getLocalMessageCount(): Promise<Result<number>> {
    return this._mapLocalStorageResult(this.localStorage.getMessageCount());
  }

  // ============ 私有助手 ============

  /** ChatMessage → LocalMessage：丢弃 wire 字段，注入 storage 层的 sessionId=""。 */
  private _chatToLocal(message: ChatMessage): LocalMessage {
    return LocalMessage.from({
      id: message.id,
      role: message.role,
      content: message.content,
      createdAt: message.createdAt,
      sessionId: "",
    });
  }

  /** LocalMessage → ChatMessage：丢弃 storage 层的 sessionId。 */
  private _localToChat(local: LocalMessage): ChatMessage {
    return ChatMessage.from({
      id: local.id,
      role: local.role,
      content: local.content,
      createdAt: local.createdAt,
    });
  }

  /**
   * 把 storage 层 `Result<T>` 透传：仓库与 storage 现在共享同一全局
   * `Result<T>`（来自 `@/utils/result`），不需要任何形状转换。
   * 该方法保留仅为未来万一又出现差异化时方便快速插入适配。
   */
  private async _mapLocalStorageResult<T>(
    promise: Promise<Result<T>>,
  ): Promise<Result<T>> {
    return await promise;
  }
}

/** 全局单例。 */
export const chatRepository = new ChatRepository(
  chatApi,
  LocalChatStorage.getInstance(),
);
