// HLDP-ZY://agents/zhuyuan-dev-agent/modules/notion-poller
// @guardian: ICE-GL-ZY001 · 铸渊
// @sovereign: TCS-0002∞ · 冰朔
// @copyright: 国作登字-2026-A-00037559
// Notion 任务轮询模块 v3.0 — select 类型修复 + 新数据库

const https = require("https");
const fs = require("fs");
const path = require("path");

const NOTION_BASE = "https://api.notion.com/v1";
const NOTION_VERSION = "2022-06-28";

function getHeaders() {
  const token = process.env.NOTION_TOKEN;
  if (!token) return null;
  return {
    "Authorization": "Bearer " + token,
    "Content-Type": "application/json",
    "Notion-Version": NOTION_VERSION
  };
}

function notionPost(endpoint, body, method) {
  return new Promise((resolve, reject) => {
    const headers = getHeaders();
    if (!headers) return reject(new Error("NOTION_TOKEN 未配置"));
    const url = new URL(NOTION_BASE + endpoint);
    const data = JSON.stringify(body);
    const req = https.request({
      hostname: url.hostname, path: url.pathname, method: method || "POST",
      headers: { ...headers, "Content-Length": Buffer.byteLength(data) },
      timeout: 15000
    }, (res) => {
      let d = "";
      res.on("data", c => d += c);
      res.on("end", () => {
        try {
          const json = JSON.parse(d);
          if (res.statusCode >= 400) reject(new Error("Notion " + res.statusCode + ": " + (json.message || d.slice(0,200))));
          else resolve(json);
        } catch(e) { reject(new Error("Notion parse: " + d.slice(0,200))); }
      });
    });
    req.on("error", reject);
    req.on("timeout", () => { req.destroy(); reject(new Error("Notion timeout")); });
    req.write(data);
    req.end();
  });
}

async function testConnection() {
  const dbId = process.env.NOTION_PLAN_DB_ID;
  const token = process.env.NOTION_TOKEN;
  if (!token) return { ok: false, error: "NOTION_TOKEN 未配置" };
  if (!dbId) return { ok: false, error: "NOTION_PLAN_DB_ID 未配置" };
  try {
    const result = await notionPost("/databases/" + dbId + "/query", { page_size: 1 });
    return { ok: true, has_results: (result.results || []).length > 0, db_id: dbId };
  } catch (err) {
    return { ok: false, error: err.message, db_id: dbId };
  }
}

async function fetchPendingTasks(options = {}) {
  const dbId = options.dbId || process.env.NOTION_PLAN_DB_ID;
  if (!dbId) throw new Error("NOTION_PLAN_DB_ID 未配置");

  // v3.0: 新数据库状态是 select 类型，不是 status
  const result = await notionPost("/databases/" + dbId + "/query", {
    sorts: [{ property: "任务标题", direction: "descending" }],
    filter: { or: [
      { property: "状态", select: { equals: "待开发" } },
      { property: "状态", select: { equals: "开发中" } },
      { property: "状态", select: { equals: "已审查" } }
    ]},
    page_size: options.pageSize || 10
  });

  return (result.results || []).map(page => {
    const props = page.properties || {};
    const titleProp = props["任务标题"]?.title;
    const stepsProp = props["开发步骤"]?.rich_text;
    const constraintsProp = props["约束"]?.rich_text;
    return {
      notion_page_id: page.id,
      title: Array.isArray(titleProp) && titleProp.length > 0 ? (titleProp[0]?.plain_text || "无标题") : "无标题",
      status: props["状态"]?.select?.name || "unknown",
      task_id: page.id.replace(/-/g,"").slice(0,12),
      priority: props["优先级"]?.select?.name || "中等",
      steps: Array.isArray(stepsProp) ? stepsProp.map(t => t.plain_text).join("\n") : "",
      constraints: Array.isArray(constraintsProp) ? constraintsProp.map(t => t.plain_text).join("\n") : "",
      developer: (props["开发者"]?.rich_text || [{}])[0]?.plain_text || "",
      server: (props["服务器"]?.rich_text || [{}])[0]?.plain_text || "",
      created: page.created_time,
      url: page.url
    };
  });
}

async function markInProgress(pageId) {
  return notionPost("/pages/" + pageId, { properties: { "状态": { select: { name: "开发中" } } } }, "PATCH");
}

async function markDone(pageId, details = {}) {
  return notionPost("/pages/" + pageId, { properties: { "状态": { select: { name: "已完成" } } } }, "PATCH");
}

async function wakeAndCheck(options = {}) {
  const log = options.log || console.log;
  log("");
  log("=== BD001 唤醒 · Notion 任务轮询 v3.0 ===");
  log("时间: " + new Date().toISOString());

  const token = process.env.NOTION_TOKEN;
  if (!token) {
    log("NOTION_TOKEN 未配置");
    return { ok: false, error: "NOTION_TOKEN 未配置", tasks: [] };
  }

  let tasks = [];
  try {
    tasks = await fetchPendingTasks({ dbId: options.dbId, pageSize: options.pageSize || 5 });
    log("查询到 " + tasks.length + " 个任务 (待开发+开发中+已审查)");
  } catch (err) {
    log("Notion查询失败: " + err.message);
    return { ok: false, error: "Notion查询失败: " + err.message, tasks: [] };
  }

  let marked = 0;
  for (const task of tasks) {
    if (task.status === "待开发") {
      try {
        await markInProgress(task.notion_page_id);
        marked++;
        log("  ✅ " + task.title + " (" + task.priority + ")");
      } catch (err) {
        log("  ⚠️ 标记失败: " + task.title + " - " + err.message);
      }
    }
  }

  const plansDir = options.plansDir || path.join(__dirname, "..", "plans");
  if (!fs.existsSync(plansDir)) fs.mkdirSync(plansDir, { recursive: true });
  for (const task of tasks) {
    const planFile = path.join(plansDir, task.task_id + ".json");
    if (!fs.existsSync(planFile)) {
      fs.writeFileSync(planFile, JSON.stringify({
        plan_id: task.task_id,
        title: task.title,
        priority: task.priority,
        steps: task.steps,
        constraints: task.constraints,
        notion_page_id: task.notion_page_id,
        notion_url: task.url,
        _received: new Date().toISOString(),
        _source: "notion",
        _status: "received",
        tasks: []
      }, null, 2), "utf-8");
      log("  📋 " + task.task_id);
    }
  }

  return {
    ok: true,
    tasks_found: tasks.length,
    tasks_marked: marked,
    tasks: tasks.map(t => ({ id: t.task_id, title: t.title, priority: t.priority })),
    time: new Date().toISOString()
  };
}

module.exports = { wakeAndCheck, fetchPendingTasks, markInProgress, markDone, testConnection };
