/**
 * chat-worker.js
 *
 * 巡检 Worker — 定时轮询 WAITING_REPLY 状态的对话，
 * 检测商家新回复 → LLM 解析 → 推进轮次或剔除 → 发送下一轮话术。
 *
 * 用法：
 *   node ./src/chat-worker.js
 *
 * 环境变量 (.env)：
 *   SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY (必填，兼容 VITE_SUPABASE_SERVICE_ROLE_KEY)
 *   CHATBOT_INTENT_LLM_PROVIDER + 对应 Provider 凭证，或 legacy LLM_API_KEY/LLM_BASE_URL/LLM_MODEL
 *   HEADLESS           无头模式 (默认 0)
 *   WORKER_BATCH_SIZE  每轮拉取任务数 (默认 5)
 *   WORKER_IDLE_SEC    队列空时休眠秒数 (默认 30)
 */

import { existsSync } from "node:fs";
import { mkdir } from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import { setTimeout as sleep } from "node:timers/promises";
import { fileURLToPath } from "node:url";
import { chromium } from "playwright";

import { antiDetectPause, attachVerificationMonitor, randomBetween } from "./human.js";
import { chatPause } from "./human.js";
import { getMessageForRound } from "./chat-templates.js";
import {
  fetchPendingChecks,
  fetchPendingSends,
  getBatchTaskSummary,
  advanceRound,
  deferCheck,
  markSent,
  logMessage,
  syncScrapedMessages,
  STATUS,
} from "./chat-scheduler.js";
import {
  openAndScrapeMessages,
  sendMessageInExistingChat,
  getMessageHash,
} from "./wangwang-rpa.js";
import { analyzeReply } from "./llm-intent.js";
import { createResolvedSupabaseClient } from "./supabase-client.js";

// ── 路径 & 配置 ─────────────────────────────────────

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PLAYWRIGHT_DIR = path.resolve(__dirname, "..");

// 加载 .env
const envPaths = [
  path.resolve(process.cwd(), ".env"),
  path.resolve(PLAYWRIGHT_DIR, ".env"),
];
for (const p of envPaths) {
  if (existsSync(p)) {
    const dotenv = await import("dotenv");
    dotenv.config({ path: p });
    break;
  }
}

const PROFILE_DIR = path.join(PLAYWRIGHT_DIR, ".browser", "1688-profile");
const PROFILE_DIR_OVERRIDE = process.env.CHAT_1688_PROFILE_DIR ?? process.env.SEARCH_1688_PROFILE_DIR ?? "";
const HEADLESS = process.env.HEADLESS === "1";
const WORKER_BATCH_SIZE = Number.parseInt(process.env.WORKER_BATCH_SIZE ?? "5", 10);
const WORKER_IDLE_SEC = Number.parseInt(process.env.WORKER_IDLE_SEC ?? "30", 10);
const CHAT_BATCH_ID = process.env.CHAT_BATCH_ID ?? "";
const WORKER_EXIT_ON_IDLE = process.env.WORKER_EXIT_ON_IDLE === "1";

function resolveProfileDir() {
  if (!PROFILE_DIR_OVERRIDE) {
    return PROFILE_DIR;
  }

  return path.isAbsolute(PROFILE_DIR_OVERRIDE)
    ? PROFILE_DIR_OVERRIDE
    : path.resolve(process.cwd(), PROFILE_DIR_OVERRIDE);
}

// ── Supabase ─────────────────────────────────────────

function initSupabase() {
  return createResolvedSupabaseClient(process.env);
}

function normalizeScrapedMerchantMessages(messages) {
  return (Array.isArray(messages) ? messages : [])
    .map((message) => ({
      sender: message?.sender,
      text: String(message?.text ?? "").replace(/\s+/g, " ").trim(),
    }))
    .filter((message) => message.text && message.sender !== "self");
}

function getPendingMerchantMessages(messages, lastProcessedHash) {
  const merchantMessages = normalizeScrapedMerchantMessages(messages).map((message) => ({
    ...message,
    messageHash: getMessageHash(message.text),
  }));

  if (merchantMessages.length === 0) {
    return [];
  }

  const latestMerchantHash = merchantMessages[merchantMessages.length - 1]?.messageHash ?? "";
  if (lastProcessedHash && latestMerchantHash === lastProcessedHash) {
    return [];
  }

  if (!lastProcessedHash) {
    return merchantMessages;
  }

  const lastProcessedIndex = merchantMessages.map((message) => message.messageHash).lastIndexOf(lastProcessedHash);
  if (lastProcessedIndex >= 0) {
    return merchantMessages.slice(lastProcessedIndex + 1);
  }

  return merchantMessages;
}

// ── 单任务处理：巡检回复 ─────────────────────────────

async function processCheck(supabase, context, task) {
  const taskId = task.id;
  const currentRound = task.current_round;
  console.log(`\n  📋 巡检任务 [${taskId.slice(0, 8)}...] 商家: ${task.merchant_name || task.contact_handle}`);
  console.log(`     当前轮次: ${currentRound}, 重试: ${task.retry_count}`);

  try {
    // 1. 打开旺旺抓取消息
    const scrapeResult = await openAndScrapeMessages(context, task);

    if (!scrapeResult.ok) {
      console.log(`     ⚠️ 消息抓取失败: ${scrapeResult.reason}`);
      // 抓取失败不改 status，仅推迟下次检查
      await deferCheck(supabase, taskId, task.retry_count);
      return;
    }

    await syncScrapedMessages(supabase, {
      chatId: taskId,
      round: currentRound,
      messages: scrapeResult.messages ?? [],
    });

    // 2. 判断是否有未处理的新商家回复
    const pendingMerchantMessages = getPendingMerchantMessages(scrapeResult.messages, task.last_message_hash);

    if (pendingMerchantMessages.length === 0) {
      console.log("     ⏳ 商家暂未回复新消息");
      const { timedOut, retryCount } = await deferCheck(supabase, taskId, task.retry_count);
      if (timedOut) {
        console.log("     ❌ 超时未回复，已放弃");
      } else {
        console.log(`     🔄 推迟至下次检查 (retry: ${retryCount})`);
      }
      return;
    }

    const latestMerchantReply = pendingMerchantMessages[pendingMerchantMessages.length - 1];
    const merchantReplyText = pendingMerchantMessages.map((message) => message.text).join("\n");
    console.log(`     ✅ 发现商家新回复 ${pendingMerchantMessages.length} 条: "${merchantReplyText.slice(0, 60)}"`);

    // 4. LLM 意图解析
    const llmResult = await analyzeReply(
      merchantReplyText,
      currentRound,
      task.ask_context || {},
    );

    // 记录 LLM 解析结果到消息日志
    await logMessage(supabase, {
      chatId: taskId,
      round: currentRound,
      direction: "RECEIVED",
      content: `[LLM 分析] ${JSON.stringify(llmResult)}`,
      llmIntent: llmResult,
    });

    // 5. 状态流转
    const { nextStatus, nextRound } = await advanceRound(
      supabase,
      taskId,
      currentRound,
      llmResult,
      latestMerchantReply?.messageHash ?? null,
    );
    console.log(`     📊 LLM 判定: passed=${llmResult.passed}, 新状态: ${nextStatus}`);

    // 6. 如果推进到下一轮，发送下一轮话术
    if (nextStatus === STATUS.PENDING_SEND && nextRound) {
      const nextMessage = getMessageForRound(nextRound, task.ask_context || {});
      console.log(`     💬 发送第 ${nextRound} 轮话术: "${nextMessage.slice(0, 50)}..."`);

      const sendResult = await sendMessageInExistingChat(context, task, nextMessage);

      if (sendResult.status === "sent") {
        const msgHash = getMessageHash(nextMessage);
        await markSent(supabase, taskId, msgHash);
        await logMessage(supabase, {
          chatId: taskId,
          round: nextRound,
          direction: "SENT",
          content: nextMessage,
          messageHash: msgHash,
        });
        console.log(`     ✅ 已推进至第 ${nextRound} 轮，等待回复`);
      } else {
        console.log(`     ⚠️ 发送失败: ${sendResult.reason}，保持 PENDING_SEND 状态`);
      }
    }
  } catch (error) {
    console.error(`     ❌ 处理任务 [${taskId.slice(0, 8)}] 时发生错误: ${error.message}`);
    // 出错不改 status，仅推迟下次检查
    await deferCheck(supabase, taskId, task.retry_count).catch(() => {});
  }
}

// ── 单任务处理：首发/重试发送 ────────────────────────

async function processSend(supabase, context, task) {
  const taskId = task.id;
  const round = task.current_round;
  console.log(`\n  📤 发送任务 [${taskId.slice(0, 8)}...] 商家: ${task.merchant_name || task.contact_handle}`);
  console.log(`     轮次: ${round}`);

  try {
    const messageText = getMessageForRound(round, task.ask_context || {});
    console.log(`     💬 话术: "${messageText.slice(0, 50)}..."`);

    const sendResult = await sendMessageInExistingChat(context, task, messageText);

    if (sendResult.status === "sent") {
      const msgHash = getMessageHash(messageText);
      await markSent(supabase, taskId, msgHash);
      await logMessage(supabase, {
        chatId: taskId,
        round,
        direction: "SENT",
        content: messageText,
        messageHash: msgHash,
      });
      console.log("     ✅ 发送成功，等待回复");
    } else {
      console.log(`     ⚠️ 发送失败: ${sendResult.reason}`);
    }
  } catch (error) {
    console.error(`     ❌ 发送任务 [${taskId.slice(0, 8)}] 出错: ${error.message}`);
  }
}

// ── 主循环 ───────────────────────────────────────────

async function main() {
  console.log("\n╔══════════════════════════════════════════════════════╗");
  console.log("║   旺旺多轮询价 — 巡检 Worker                        ║");
  console.log("╚══════════════════════════════════════════════════════╝\n");

  const supabase = initSupabase();
  console.log("✅ Supabase 已连接");

  if (CHAT_BATCH_ID) {
    console.log(`🎯 仅处理批次: ${CHAT_BATCH_ID}`);
  }

  const profileDir = resolveProfileDir();
  await mkdir(profileDir, { recursive: true });
  const context = await chromium.launchPersistentContext(profileDir, {
    channel: "chrome",
    headless: HEADLESS,
    locale: "zh-CN",
    viewport: { width: 1440, height: 960 },
    args: ["--disable-blink-features=AutomationControlled"],
  });
  const verificationMonitor = attachVerificationMonitor(context, { logPrefix: "[chat-worker][验证码]" });
  console.log("✅ 浏览器已启动\n");

  try {
    while (true) {
      const now = new Date().toLocaleTimeString("zh-CN");

      // 1. 处理待发送任务 (PENDING_SEND)
      const pendingSends = await fetchPendingSends(supabase, {
        batchId: CHAT_BATCH_ID || undefined,
        limit: WORKER_BATCH_SIZE,
      }).catch((err) => {
        console.error(`  ❌ 查询待发送任务失败: ${err.message}`);
        return [];
      });

      if (pendingSends.length > 0) {
        console.log(`[${now}] 📤 ${pendingSends.length} 个待发送任务`);
        for (const task of pendingSends) {
          await processSend(supabase, context, task);
          await chatPause();
        }
      }

      // 2. 巡检等待回复的任务 (WAITING_REPLY)
      const pendingChecks = await fetchPendingChecks(supabase, {
        batchId: CHAT_BATCH_ID || undefined,
        limit: WORKER_BATCH_SIZE,
      }).catch((err) => {
        console.error(`  ❌ 查询待巡检任务失败: ${err.message}`);
        return [];
      });

      if (pendingChecks.length > 0) {
        console.log(`[${now}] 🔍 ${pendingChecks.length} 个待巡检任务`);
        for (const task of pendingChecks) {
          await processCheck(supabase, context, task);
          await chatPause();
        }
      }

      // 3. 如果两个队列都为空，休眠
      if (pendingSends.length === 0 && pendingChecks.length === 0) {
        if (CHAT_BATCH_ID && WORKER_EXIT_ON_IDLE) {
          const summary = await getBatchTaskSummary(supabase, CHAT_BATCH_ID).catch((err) => {
            console.error(`  ❌ 查询批次汇总失败: ${err.message}`);
            return null;
          });

          if (summary && summary.total > 0 && summary.active === 0) {
            console.log(`[${now}] ✅ 批次 ${CHAT_BATCH_ID} 已无活动任务，Worker 退出`);
            break;
          }
        }

        console.log(`[${now}] 💤 队列为空，休眠 ${WORKER_IDLE_SEC}s...`);
        await sleep(WORKER_IDLE_SEC * 1000);
      } else {
        // 一轮跑完稍微休息
        await sleep(randomBetween(5_000, 10_000));
      }

      // 4. 清理多余标签页
      while (context.pages().length > 1) {
        await context.pages().at(-1)?.close().catch(() => {});
      }
    }
  } finally {
    verificationMonitor.dispose();
    await context.close().catch(() => {});
  }
}

main().catch((error) => {
  console.error(`\n💥 Worker 崩溃: ${error instanceof Error ? error.message : String(error)}`);
  if (error instanceof Error && error.stack) console.error(error.stack);
  process.exitCode = 1;
});
