/**
 * chat-scheduler.js
 *
 * 对话调度器 — 管理 customer_service_chats 的状态流转、指数退避、批量初始化。
 */

import { TOTAL_ROUNDS } from "./chat-templates.js";

// ── 指数退避配置 ─────────────────────────────────────────

/** 最大轮询次数，超过后标记 TIMEOUT_REJECTED */
export const MAX_RETRIES = 10;

/** 退避基数（分钟），实际等待 = BASE * 2^retryCount，上限 60 分钟 */
const BACKOFF_BASE_MINUTES = 3;
const BACKOFF_CAP_MINUTES = 60;

/**
 * 计算下一次检查时间 (ISO string)
 * @param {number} retryCount
 * @returns {string}
 */
export function calculateNextCheckTime(retryCount) {
  const minutes = Math.min(BACKOFF_BASE_MINUTES * 2 ** retryCount, BACKOFF_CAP_MINUTES);
  const next = new Date(Date.now() + minutes * 60_000);
  return next.toISOString();
}

// ── 状态常量 ─────────────────────────────────────────────

export const STATUS = {
  PENDING_SEND: "PENDING_SEND",
  WAITING_REPLY: "WAITING_REPLY",
  R1_PASSED: "R1_PASSED",
  R2_PASSED: "R2_PASSED",
  R3_PASSED: "R3_PASSED",
  R4_PASSED: "R4_PASSED",
  REJECTED: "REJECTED",
  TIMEOUT_REJECTED: "TIMEOUT_REJECTED",
  COMPLETED: "COMPLETED",
  HUMAN_TAKEOVER: "HUMAN_TAKEOVER",
};

const TERMINAL_STATUSES = new Set([
  STATUS.COMPLETED,
  STATUS.REJECTED,
  STATUS.TIMEOUT_REJECTED,
  STATUS.HUMAN_TAKEOVER,
]);

const ROUND_PASSED_STATUS = {
  1: STATUS.R1_PASSED,
  2: STATUS.R2_PASSED,
  3: STATUS.R3_PASSED,
  4: STATUS.R4_PASSED,
};

// ── 批量初始化 ───────────────────────────────────────────

/**
 * 从搜索结果批量创建 customer_service_chats 记录
 *
 * @param {import("@supabase/supabase-js").SupabaseClient} supabase
 * @param {object} opts
 * @param {string} opts.batchId
 * @param {object} opts.material   procurement_materials 行
 * @param {object[]} opts.searchResults  extractTopResults() 的输出
 * @returns {Promise<object[]>} 创建的 chat 记录数组
 */
export async function initChatTasks(supabase, { batchId, material, searchResults }) {
  const rows = searchResults.map((result) => ({
    intent_id: material.id ?? null,
    search_result_id: result.searchResultId ?? null,
    batch_id: batchId,
    merchant_id: result.contact?.handle || "",
    merchant_name: result.merchantName || "",
    merchant_url: result.merchantUrl || "",
    contact_url: result.contact?.url || "",
    contact_handle: result.contact?.handle || "",
    contact_site: result.contact?.site || "",
    offer_url: result.offerUrl || "",
    title: result.title || "",
    current_round: 1,
    status: STATUS.PENDING_SEND,
    ask_context: {
      title: result.title,
      material_name: material.material_name,
      specification: material.specification || "",
      quantity: material.quantity || "",
      unit: material.unit || "",
      brand: material.brand || "",
      technical_standard: material.technical_standard || "",
      material_requirement: material.material_requirement || "",
    },
  }));

  if (rows.length === 0) return [];

  const { data, error } = await supabase
    .from("customer_service_chats")
    .insert(rows)
    .select("*");

  if (error) {
    throw new Error(`创建 customer_service_chats 失败: ${error.message}`);
  }

  return data;
}

// ── 状态流转 ─────────────────────────────────────────────

/**
 * 标记消息已发送，进入等待回复状态
 */
export async function markSent(supabase, chatId, messageHash) {
  const { error } = await supabase
    .from("customer_service_chats")
    .update({
      status: STATUS.WAITING_REPLY,
      next_check_time: calculateNextCheckTime(0),
      retry_count: 0,
      last_interacted_at: new Date().toISOString(),
      updated_at: new Date().toISOString(),
    })
    .eq("id", chatId);

  if (error) throw new Error(`markSent 失败: ${error.message}`);
}

/**
 * 根据 LLM 分析结果推进轮次
 *
 * @param {object} supabase
 * @param {string} chatId
 * @param {number} currentRound
 * @param {object} llmResult  { passed: boolean, status?: string, ...extracted }
 * @param {string|null} [lastReceivedHash]
 * @returns {Promise<{nextStatus: string, nextRound: number|null}>}
 */
export async function advanceRound(supabase, chatId, currentRound, llmResult, lastReceivedHash = null) {
  const receivedUpdate = {
    last_message_hash: lastReceivedHash || null,
    last_interacted_at: new Date().toISOString(),
    updated_at: new Date().toISOString(),
  };

  // LLM 返回 PENDING / UNCLEAR → 人工接管
  if (llmResult.status === "PENDING" || llmResult.status === "UNCLEAR") {
    await supabase
      .from("customer_service_chats")
      .update({
        ...receivedUpdate,
        status: STATUS.HUMAN_TAKEOVER,
        extracted_data: llmResult,
      })
      .eq("id", chatId);
    return { nextStatus: STATUS.HUMAN_TAKEOVER, nextRound: null };
  }

  // 不通过 → 剔除
  if (!llmResult.passed) {
    await supabase
      .from("customer_service_chats")
      .update({
        ...receivedUpdate,
        status: STATUS.REJECTED,
        extracted_data: llmResult,
      })
      .eq("id", chatId);
    return { nextStatus: STATUS.REJECTED, nextRound: null };
  }

  // 通过：标记当前轮次 PASSED
  const passedStatus = ROUND_PASSED_STATUS[currentRound];

  // 最后一轮通过 → COMPLETED
  if (currentRound >= TOTAL_ROUNDS) {
    await supabase
      .from("customer_service_chats")
      .update({
        ...receivedUpdate,
        status: STATUS.COMPLETED,
        current_round: currentRound,
        extracted_data: llmResult,
      })
      .eq("id", chatId);
    return { nextStatus: STATUS.COMPLETED, nextRound: null };
  }

  // 还有下一轮 → 更新轮次，设为 PENDING_SEND
  const nextRound = currentRound + 1;
  await supabase
    .from("customer_service_chats")
    .update({
      ...receivedUpdate,
      status: STATUS.PENDING_SEND,
      current_round: nextRound,
      extracted_data: llmResult,
    })
    .eq("id", chatId);

  return { nextStatus: STATUS.PENDING_SEND, nextRound };
}

/**
 * 无新回复时指数退避
 */
export async function deferCheck(supabase, chatId, currentRetryCount) {
  const newRetryCount = currentRetryCount + 1;

  if (newRetryCount > MAX_RETRIES) {
    await supabase
      .from("customer_service_chats")
      .update({
        status: STATUS.TIMEOUT_REJECTED,
        updated_at: new Date().toISOString(),
      })
      .eq("id", chatId);
    return { timedOut: true };
  }

  await supabase
    .from("customer_service_chats")
    .update({
      retry_count: newRetryCount,
      next_check_time: calculateNextCheckTime(newRetryCount),
      updated_at: new Date().toISOString(),
    })
    .eq("id", chatId);

  return { timedOut: false, retryCount: newRetryCount };
}

/**
 * 拉取到期的待巡检任务
 */
export async function fetchPendingChecks(supabase, { batchId, limit = 5 } = {}) {
  let query = supabase
    .from("customer_service_chats")
    .select("*")
    .eq("status", STATUS.WAITING_REPLY)
    .lte("next_check_time", new Date().toISOString())
    .order("next_check_time", { ascending: true })
    .limit(limit);

  if (batchId) {
    query = query.eq("batch_id", batchId);
  }

  const { data, error } = await query;

  if (error) throw new Error(`fetchPendingChecks 失败: ${error.message}`);
  return data ?? [];
}

/**
 * 拉取待发送任务 (首轮或下一轮)
 * @param {object} supabase
 * @param {object} [opts]
 * @param {string} [opts.batchId]  可选，按批次过滤
 * @param {number} [opts.limit]    默认 50
 */
export async function fetchPendingSends(supabase, { batchId, limit = 50 } = {}) {
  let query = supabase
    .from("customer_service_chats")
    .select("*")
    .eq("status", STATUS.PENDING_SEND)
    .order("created_at", { ascending: true })
    .limit(limit);

  if (batchId) {
    query = query.eq("batch_id", batchId);
  }

  const { data, error } = await query;
  if (error) throw new Error(`fetchPendingSends 失败: ${error.message}`);
  return data ?? [];
}

export async function getBatchTaskSummary(supabase, batchId) {
  const { data, error } = await supabase
    .from("customer_service_chats")
    .select("status")
    .eq("batch_id", batchId);

  if (error) throw new Error(`getBatchTaskSummary 失败: ${error.message}`);

  const rows = data ?? [];
  const summary = {
    total: rows.length,
    completed: 0,
    rejected: 0,
    humanTakeover: 0,
    active: 0,
  };

  for (const row of rows) {
    if (row.status === STATUS.COMPLETED) {
      summary.completed += 1;
      continue;
    }

    if (row.status === STATUS.REJECTED || row.status === STATUS.TIMEOUT_REJECTED) {
      summary.rejected += 1;
      continue;
    }

    if (row.status === STATUS.HUMAN_TAKEOVER) {
      summary.humanTakeover += 1;
      continue;
    }

    if (!TERMINAL_STATUSES.has(row.status)) {
      summary.active += 1;
    }
  }

  return summary;
}

// ── 消息日志 ─────────────────────────────────────────────

/**
 * 记录一条聊天消息
 */
export async function logMessage(supabase, { chatId, round, direction, content, messageHash, llmIntent }) {
  const { error } = await supabase.from("chat_messages").insert({
    chat_id: chatId,
    round,
    direction,
    content,
    message_hash: messageHash || null,
    llm_intent: llmIntent || null,
  });

  if (error) {
    console.error(`  ⚠️ 消息日志写入失败: ${error.message}`);
  }
}

function normalizeMessageContent(content) {
  return String(content ?? "").replace(/\s+/g, " ").trim();
}

function normalizeScrapedDirection(sender) {
  return sender === "self" ? "SENT" : "RECEIVED";
}

function messagesEqual(left, right) {
  return left.direction === right.direction && normalizeMessageContent(left.content) === normalizeMessageContent(right.content);
}

function findConversationOverlap(existingMessages, scrapedMessages) {
  const maxOverlap = Math.min(existingMessages.length, scrapedMessages.length);

  for (let overlap = maxOverlap; overlap > 0; overlap -= 1) {
    let matched = true;

    for (let index = 0; index < overlap; index += 1) {
      const existing = existingMessages[existingMessages.length - overlap + index];
      const scraped = scrapedMessages[index];
      if (!messagesEqual(existing, scraped)) {
        matched = false;
        break;
      }
    }

    if (matched) {
      return overlap;
    }
  }

  return 0;
}

/**
 * 将旺旺抓到的最近消息窗口增量同步到 chat_messages。
 * 只同步真实聊天消息，不处理 LLM 系统日志。
 */
export async function syncScrapedMessages(supabase, { chatId, round, messages }) {
  const normalizedScrapedMessages = (Array.isArray(messages) ? messages : [])
    .map((message) => ({
      direction: normalizeScrapedDirection(message?.sender),
      content: normalizeMessageContent(message?.text),
    }))
    .filter((message) => message.content);

  if (normalizedScrapedMessages.length === 0) {
    return { appendedCount: 0 };
  }

  const { data, error } = await supabase
    .from("chat_messages")
    .select("direction, content, llm_intent, created_at")
    .eq("chat_id", chatId)
    .order("created_at", { ascending: true });

  if (error) {
    throw new Error(`同步 chat_messages 失败: ${error.message}`);
  }

  const existingVisibleMessages = (data ?? [])
    .filter((message) => !message.llm_intent)
    .map((message) => ({
      direction: message.direction,
      content: normalizeMessageContent(message.content),
    }))
    .filter((message) => message.content);

  const overlap = findConversationOverlap(existingVisibleMessages, normalizedScrapedMessages);
  const newMessages = normalizedScrapedMessages.slice(overlap);

  if (newMessages.length === 0) {
    return { appendedCount: 0 };
  }

  const { error: insertError } = await supabase.from("chat_messages").insert(
    newMessages.map((message) => ({
      chat_id: chatId,
      round,
      direction: message.direction,
      content: message.content,
    })),
  );

  if (insertError) {
    throw new Error(`写入抓取消息失败: ${insertError.message}`);
  }

  return { appendedCount: newMessages.length };
}
