/**
 * Chat 状态机：纯函数 + 数据加载
 *
 * 从 `chat-machine.ts` 抽出的"helpers"段：
 *   - 翻页大小常量
 *   - 仓库注入（接口类型 → 单例）
 *   - DTO ↔ UiMessage 映射（纯函数 —— 可单测）
 *   - Result → number 映射（纯函数 —— 可单测）
 *   - 2 个独立 init 任务的数据加载：
 *     - `readGuestQuota()` —— 游客日配 + 总配（仅游客有意义，纯 ChatStorage）
 *     - `readAndSyncHistory()` —— local → network → save network to local 3 步
 *
 * 设计目标：
 *   - helpers 无 XState 依赖（可独立 import / 测试）
 *   - actors 依赖 helpers（import）
 *   - machine 依赖 actors（import）—— 不直接依赖 helpers
 *
 * 历史：
 *   - `readInitData` + `InitResult` 已删（被 2 个独立 helper 替换）
 *   - `AuthStorage` import 已删（只 `readInitData` 用过，移到 `chatInit` actor 上层调用）
 */

import type { UiMessage } from "@/data/dto/chat";
import { chatRepository } from "@/data/repositories/chat_repository";
import type { IChatRepository } from "@/data/repositories/interfaces";
import { ChatStorage } from "@/data/storage/chat/chat_storage";
import { ChatSendResponse } from "@/data/dto/chat/chat_send_response";
import { formatDate, Result, Logger } from "@/utils";

const log = new Logger("StoresChatChatMachineHelpers");

// ============================================================
// Constants
// ============================================================
/** 翻历史每页大小（仅 `loadMoreHistoryActor` 用） */
export const PAGE_SIZE = 50;

// ============================================================
// Repository injection
// ============================================================
// 仓库以接口类型注入：调用面只看接口，运行时仍是同一单例
export const chatRepo: IChatRepository = chatRepository;

// ============================================================
// DTO ↔ UiMessage 映射
// ============================================================
/**
 * ChatMessage[] → UiMessage[]（纯函数）
 * - 与 Dart `LocalMessage → ChatMessage` 等价
 * - 业务事实：`role === "assistant"` → `isFromAI: true`
 */
export function localMessagesToUi(
  records: ReadonlyArray<{
    content: string;
    role: string;
    createdAt: string;
  }>,
): UiMessage[] {
  return records.map((m) => ({
    content: m.content,
    isFromAI: m.role === "assistant",
    date: m.createdAt,
  }));
}

/**
 * ChatSendResponse → UiMessage（纯函数）
 * - 业务事实：后端响应就是 AI 的回复
 * - 用后端 `timestamp`（不用本地 time）—— 多设备/时区一致
 */
export function sendResponseToUiMessage(response: ChatSendResponse): UiMessage {
  return {
    content: response.reply,
    isFromAI: true,
    date: formatDate(new Date(response.timestamp)),
  };
}

// ============================================================
// Result → number 映射
// ============================================================
/** 日配额 Result → number（纯函数） */
export function mapQuotaResult(
  r: Result<{ remaining: number } | null>,
  fallback: number,
): number {
  if (r.success && r.data != null) return r.data.remaining;
  return fallback;
}

/** 总配额 Result → number（纯函数） */
export function mapTotalQuotaResult(
  r: Result<number | null>,
  fallback: number,
): number {
  if (r.success && r.data != null) return r.data;
  return fallback;
}

export async function readGuestQuota(): Promise<{
  remaining: number;
  total: number;
}> {
  const chatStorage = ChatStorage.getInstance();
  const [dailyResult, totalResult] = await Promise.all([
    chatStorage.getGuestDailyChatQuota(),
    chatStorage.getGuestTotalQuota(),
  ]);
  return {
    remaining: mapQuotaResult(
      dailyResult as Result<{ remaining: number } | null>,
      0,
    ),
    total: mapTotalQuotaResult(totalResult as Result<number | null>, 0),
  };
}

// ============================================================
// Init 任务 2：history 3 步流（local → network → save）—— `loadHistoryActor` 调
// ============================================================
/**
 * 拉 history 流程（每步都记日志 —— 用户要求"不要删除"）
 *   1. 读 local（chatRepo.getLocalMessages）→ 返 localMessages
 *   2. 读 network（chatRepo.getHistory）→ 返 networkMessages
 *   3. 用 network 覆盖 local（chatRepo.saveMessagesToLocal）→ local 被同步
 *
 * 返回 network 最终 messages（authorititative），不返 local（UI 不需要过渡态）
 *
 * 保留日志（前缀 `[chat-machine]` 与 chat-machine.actors.ts 对齐）
 */
export async function readAndSyncHistory(): Promise<{
  messages: UiMessage[];        // network 最终 messages（authorititative）
  hasMore: boolean;
  newOffset: number;
  localOverwritten: boolean;     // true = local 已被 network 覆盖（写入 ChatStorage）
  /** 真实从 local 读到的消息数（调试用） */
  localCount: number;
  /** 真实从 network 读到的消息数（调试用） */
  networkCount: number;
}> {
  /**
   * 空历史首屏欢迎语（AI persona 首条消息）。
   * 触发条件：最终返回的 messages 为空（network 空 + local 空 / 或 network 失败且 local 空）。
   *
   * 不主动持久化到 local —— 这是纯 UI 层"首屏不空"的兜底：
   *   - 用户一旦发了消息，network 上有真实消息 → 后续 readAndSyncHistory
   *     返回的 messages 非空，不会再触发本条
   *   - 用户从未发过消息就关掉 app 再开，仍然没 network 消息 → 会再次显示本条
   *     （"每次冷启动给个温暖的起点" —— 若要"只显示一次"，需额外存 local）
   */
  const greetingMessage: UiMessage = {
    content:
      "You're here! Facebook is so restrictive, " +
      "there were things I couldn't say there. " +
      "Finally I can relax. How was your day out?",
    isFromAI: true,
    date: formatDate(),
  };

  // 1. 读 local
  const localResult = await chatRepo.getLocalMessages();
  const localMessages =
    Result.isOk(localResult) && localResult.data
      ? localMessagesToUi(localResult.data)
      : [];
  log.debug("[chat-machine] loadHistory LOCAL DONE", {
    count: localMessages.length,
  });

  // 2. 读 network
  const networkResult = await chatRepo.getHistory(PAGE_SIZE, 0);
  if (!Result.isOk(networkResult)) {
    // network 失败 —— 返空 messages（不让 UI 卡住）
    log.error(
      "[chat-machine] loadHistory NETWORK FAILED",
      networkResult.success ? null : (networkResult as { error: unknown }).error,
    );

    // 空历史 → fallback 也走 welcome（不让屏幕空空如也）
    const fallbackMessages =
      localMessages.length === 0 ? [greetingMessage] : localMessages;
    if (fallbackMessages[0] === greetingMessage) {
      log.debug(
        "[chat-machine] loadHistory EMPTY → prepend greeting (network-failed path)",
      );
    }
    return {
      messages: fallbackMessages,
      hasMore: false,
      newOffset: fallbackMessages.length,
      localOverwritten: false,
      localCount: localMessages.length,
      networkCount: 0,
    };
  }
  const networkUi = localMessagesToUi(networkResult.data.messages);
  log.debug("[chat-machine] loadHistory NETWORK DONE", {
    count: networkUi.length,
  });

  // 3. 用 network 覆盖 local
  const saveResult = await chatRepo.saveMessagesToLocal(networkResult.data.messages);
  const localOverwritten = Result.isOk(saveResult);
  log.debug("[chat-machine] loadHistory SAVE TO LOCAL DONE", {
    localOverwritten,
  });

  // 空历史 → prepend welcome（network 权威为空 = 用户从未发过消息）
  const finalMessages =
    networkUi.length === 0 ? [greetingMessage] : networkUi;
  if (finalMessages[0] === greetingMessage) {
    log.debug("[chat-machine] loadHistory EMPTY → prepend greeting");
  }

  return {
    messages: finalMessages, // authoritative（empty 时塞 greeting）
    hasMore: finalMessages.length >= PAGE_SIZE,
    newOffset: finalMessages.length,
    localOverwritten,
    localCount: localMessages.length,
    networkCount: networkUi.length,
  };
}
