import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { existsSync, readFileSync } from "fs";
import { join } from "path";
import { homedir } from "os";
import {
  sendNotification,
  loadSMSConfig,
  saveSMSConfig
} from "./sms-notify.js";
import { writeFileSecure, ensureSecureDir } from "./secure-fs.js";
import { SyncOptionsSchema, parseConfigSafe } from "./schemas.js";
import {
  frameLifecycleHooks
} from "../core/context/frame-lifecycle-hooks.js";
const SYNC_CONFIG_PATH = join(homedir(), ".stackmemory", "whatsapp-sync.json");
const DEFAULT_SYNC_OPTIONS = {
  autoSyncOnClose: false,
  minFrameDuration: 30,
  // Skip frames shorter than 30 seconds
  includeDecisions: true,
  includeFiles: true,
  includeTests: true,
  maxDigestLength: 400
};
function loadSyncOptions() {
  try {
    if (existsSync(SYNC_CONFIG_PATH)) {
      const data = JSON.parse(readFileSync(SYNC_CONFIG_PATH, "utf8"));
      return parseConfigSafe(
        SyncOptionsSchema,
        { ...DEFAULT_SYNC_OPTIONS, ...data },
        DEFAULT_SYNC_OPTIONS,
        "whatsapp-sync"
      );
    }
  } catch {
  }
  return { ...DEFAULT_SYNC_OPTIONS };
}
function saveSyncOptions(options) {
  try {
    ensureSecureDir(join(homedir(), ".stackmemory"));
    writeFileSecure(SYNC_CONFIG_PATH, JSON.stringify(options, null, 2));
  } catch {
  }
}
function formatDuration(seconds) {
  if (seconds < 60) {
    return `${seconds}s`;
  } else if (seconds < 3600) {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return secs > 0 ? `${mins}m${secs}s` : `${mins}m`;
  } else {
    const hours = Math.floor(seconds / 3600);
    const mins = Math.floor(seconds % 3600 / 60);
    return mins > 0 ? `${hours}h${mins}m` : `${hours}h`;
  }
}
function truncate(text, maxLen) {
  if (text.length <= maxLen) return text;
  return text.slice(0, maxLen - 3) + "...";
}
function getStatusSymbol(status) {
  switch (status) {
    case "success":
      return "OK";
    case "failure":
      return "FAIL";
    case "partial":
      return "PARTIAL";
    case "ongoing":
      return "ACTIVE";
    default:
      return "?";
  }
}
function generateMobileDigest(data, options = DEFAULT_SYNC_OPTIONS) {
  const parts = [];
  const maxLen = options.maxDigestLength;
  const header = `FRAME: ${truncate(data.name, 30)} [${data.type}] - ${formatDuration(data.durationSeconds)} ${getStatusSymbol(data.status)}`;
  parts.push(header);
  const activityParts = [];
  if (options.includeFiles && data.filesModified.length > 0) {
    activityParts.push(`FILES: ${data.filesModified.length}`);
  }
  if (data.toolCallCount > 0) {
    activityParts.push(`TOOLS: ${data.toolCallCount}`);
  }
  if (options.includeTests && data.testsRun.length > 0) {
    const passed = data.testsRun.filter((t) => t.status === "passed").length;
    const failed = data.testsRun.filter((t) => t.status === "failed").length;
    if (failed > 0) {
      activityParts.push(`TESTS: ${passed}ok/${failed}fail`);
    } else {
      activityParts.push(`TESTS: ${passed} pass`);
    }
  }
  if (activityParts.length > 0) {
    parts.push(activityParts.join(" | "));
  }
  if (options.includeFiles && data.filesModified.length > 0) {
    const fileList = data.filesModified.slice(0, 3).map((f) => {
      const basename = f.path.split("/").pop() || f.path;
      const op = f.operation.charAt(0).toUpperCase();
      return `${op}:${truncate(basename, 20)}`;
    }).join(", ");
    const more = data.filesModified.length > 3 ? ` +${data.filesModified.length - 3}` : "";
    parts.push(`  ${fileList}${more}`);
  }
  if (options.includeDecisions && data.decisions.length > 0) {
    parts.push("");
    parts.push("DECISIONS:");
    data.decisions.slice(0, 3).forEach((d) => {
      parts.push(`  ${truncate(d, 60)}`);
    });
    if (data.decisions.length > 3) {
      parts.push(`  +${data.decisions.length - 3} more`);
    }
  }
  if (data.risks.length > 0) {
    parts.push("");
    parts.push("RISKS:");
    data.risks.slice(0, 2).forEach((r) => {
      parts.push(`  ${truncate(r, 50)}`);
    });
  }
  const unresolvedErrors = data.errors.filter((e) => !e.resolved);
  if (unresolvedErrors.length > 0) {
    parts.push("");
    parts.push(`ERRORS: ${unresolvedErrors.length} unresolved`);
    unresolvedErrors.slice(0, 2).forEach((e) => {
      parts.push(`  ${truncate(e.message, 50)}`);
    });
  }
  parts.push("");
  if (data.status === "success") {
    parts.push("NEXT: commit & test");
  } else if (data.status === "failure") {
    parts.push("NEXT: fix errors");
  } else if (data.status === "partial") {
    parts.push("NEXT: review & continue");
  } else {
    parts.push("NEXT: check status");
  }
  let result = parts.join("\n");
  if (result.length > maxLen) {
    const essentialParts = [header];
    if (activityParts.length > 0) {
      essentialParts.push(activityParts.join(" | "));
    }
    if (options.includeDecisions && data.decisions.length > 0) {
      essentialParts.push("");
      essentialParts.push(`DECISIONS: ${data.decisions.length}`);
      essentialParts.push(`  ${truncate(data.decisions[0], 50)}`);
    }
    if (unresolvedErrors.length > 0) {
      essentialParts.push("");
      essentialParts.push(`ERRORS: ${unresolvedErrors.length} unresolved`);
    }
    essentialParts.push("");
    essentialParts.push(
      data.status === "success" ? "NEXT: commit" : "NEXT: review"
    );
    result = essentialParts.join("\n");
  }
  return result.slice(0, maxLen);
}
async function getFrameDigestData(frameId) {
  try {
    const digestPath = join(
      homedir(),
      ".stackmemory",
      "latest-frame-digest.json"
    );
    if (existsSync(digestPath)) {
      const data = JSON.parse(readFileSync(digestPath, "utf8"));
      if (frameId && data.frameId !== frameId) {
        return null;
      }
      return data;
    }
    return null;
  } catch {
    return null;
  }
}
function storeFrameDigest(data) {
  try {
    ensureSecureDir(join(homedir(), ".stackmemory"));
    const digestPath = join(
      homedir(),
      ".stackmemory",
      "latest-frame-digest.json"
    );
    writeFileSecure(digestPath, JSON.stringify(data, null, 2));
  } catch {
  }
}
async function syncContext() {
  const options = loadSyncOptions();
  const data = await getFrameDigestData();
  if (!data) {
    return {
      success: false,
      error: "No context data available. Run a task first."
    };
  }
  return syncFrameData(data, options);
}
async function syncFrame(frameId) {
  const options = loadSyncOptions();
  const data = await getFrameDigestData(frameId);
  if (!data) {
    return {
      success: false,
      error: `Frame not found: ${frameId}`
    };
  }
  return syncFrameData(data, options);
}
async function syncFrameData(data, options) {
  const config = loadSMSConfig();
  if (!config.enabled) {
    return { success: false, error: "Notifications disabled" };
  }
  if (data.durationSeconds < options.minFrameDuration) {
    return {
      success: false,
      error: `Frame too short (${data.durationSeconds}s < ${options.minFrameDuration}s min)`
    };
  }
  const digest = generateMobileDigest(data, options);
  const payload = {
    type: "custom",
    title: "Context Sync",
    message: digest,
    prompt: {
      type: "options",
      options: [
        { key: "1", label: "Commit", action: "git add -A && git commit" },
        { key: "2", label: "Status", action: "stackmemory status" },
        { key: "3", label: "Continue", action: 'echo "Continuing..."' }
      ],
      question: "Action?"
    }
  };
  const result = await sendNotification(payload);
  return {
    success: result.success,
    messageId: result.promptId,
    channel: result.channel,
    error: result.error,
    digestLength: digest.length
  };
}
function enableAutoSync(options) {
  const current = loadSyncOptions();
  const updated = {
    ...current,
    ...options,
    autoSyncOnClose: true
  };
  saveSyncOptions(updated);
  const smsConfig = loadSMSConfig();
  if (!smsConfig.notifyOn.custom) {
    smsConfig.notifyOn.custom = true;
    saveSMSConfig(smsConfig);
  }
}
function disableAutoSync() {
  const current = loadSyncOptions();
  current.autoSyncOnClose = false;
  saveSyncOptions(current);
}
function isAutoSyncEnabled() {
  const options = loadSyncOptions();
  return options.autoSyncOnClose;
}
async function onFrameClosed(frameData) {
  if (!isAutoSyncEnabled()) {
    return null;
  }
  storeFrameDigest(frameData);
  const options = loadSyncOptions();
  return syncFrameData(frameData, options);
}
async function handleFrameCloseHook(data) {
  const digestData = createFrameDigestData(
    data.frame,
    data.events,
    data.anchors
  );
  await onFrameClosed(digestData);
}
let hookUnregister = null;
function registerWhatsAppSyncHook() {
  if (hookUnregister) {
    return hookUnregister;
  }
  hookUnregister = frameLifecycleHooks.onFrameClosed(
    "whatsapp-sync",
    handleFrameCloseHook,
    -10
    // Low priority - run after other hooks
  );
  return () => {
    if (hookUnregister) {
      hookUnregister();
      hookUnregister = null;
    }
  };
}
function isHookRegistered() {
  return hookUnregister !== null;
}
function createFrameDigestData(frame, events, anchors) {
  const now = Math.floor(Date.now() / 1e3);
  const duration = (frame.closed_at || now) - frame.created_at;
  const filesModified = [];
  const filesSeen = /* @__PURE__ */ new Set();
  events.filter((e) => e.event_type === "tool_call").forEach((e) => {
    const path = e.payload["path"];
    if (path && !filesSeen.has(path)) {
      filesSeen.add(path);
      const toolName = e.payload["tool_name"] || "";
      let operation = "modify";
      if (toolName.includes("Write") || toolName.includes("Create")) {
        operation = "create";
      } else if (toolName.includes("Read")) {
        operation = "read";
      } else if (toolName.includes("Delete")) {
        operation = "delete";
      }
      filesModified.push({ path, operation });
    }
  });
  const testsRun = [];
  events.filter(
    (e) => e.event_type === "tool_result" && String(e.payload["output"] || "").includes("test")
  ).forEach((e) => {
    const output = String(e.payload["output"] || "");
    const passMatch = output.match(/(\d+) pass/i);
    const failMatch = output.match(/(\d+) fail/i);
    if (passMatch) {
      testsRun.push({ name: "Tests", status: "passed" });
    }
    if (failMatch && parseInt(failMatch[1]) > 0) {
      testsRun.push({ name: "Tests", status: "failed" });
    }
  });
  const decisions = anchors.filter((a) => a.type === "DECISION").map((a) => a.text);
  const risks = anchors.filter((a) => a.type === "RISK").map((a) => a.text);
  const errors = [];
  events.filter((e) => e.payload["error"] || e.payload["status"] === "error").forEach((e) => {
    const errorMsg = e.payload["error"] || e.payload["message"] || "Unknown error";
    errors.push({
      type: e.payload["type"] || "error",
      message: errorMsg,
      resolved: false
    });
  });
  let status = "ongoing";
  if (frame.closed_at) {
    if (errors.filter((e) => !e.resolved).length > 0) {
      status = "failure";
    } else if (testsRun.some((t) => t.status === "failed") || filesModified.length === 0) {
      status = "partial";
    } else {
      status = "success";
    }
  }
  const toolCallCount = events.filter(
    (e) => e.event_type === "tool_call"
  ).length;
  return {
    frameId: frame.frame_id,
    name: frame.name,
    type: frame.type,
    status,
    durationSeconds: duration,
    filesModified: filesModified.filter((f) => f.operation !== "read"),
    testsRun,
    decisions,
    risks,
    toolCallCount,
    errors
  };
}
export {
  createFrameDigestData,
  disableAutoSync,
  enableAutoSync,
  generateMobileDigest,
  getFrameDigestData,
  isAutoSyncEnabled,
  isHookRegistered,
  loadSyncOptions,
  onFrameClosed,
  registerWhatsAppSyncHook,
  saveSyncOptions,
  storeFrameDigest,
  syncContext,
  syncFrame
};
//# sourceMappingURL=whatsapp-sync.js.map
