import {
  createJob,
  deleteJob,
  getJob,
  listJobs,
  setJobStatus
} from "../watch/store.js";
import { runCheck } from "../watch/scheduler.js";
import { guardUrl } from "../watch/ssrf.js";
import { createLogger } from "../logger.js";
const log = createLogger("cache");
const MIN_INTERVAL_SECONDS = 60;
const MAX_WATCH_BATCH_SIZE = 1e3;
function badInput(reason, hint) {
  return {
    ok: false,
    error: "invalid_input",
    error_reason: reason,
    stage: "watch",
    ...hint ? { hint } : {}
  };
}
function missing(field, action) {
  return badInput(`watch action=${action} requires "${field}"`, `Set "${field}" on the input.`);
}
async function handleWatch(input, router) {
  const action = input?.action;
  if (!action) {
    return badInput('watch input requires "action"', 'Set "action" to create | list | check | pause | resume | delete.');
  }
  if (action === "list") {
    return { ok: true, data: { jobs: listJobs() } };
  }
  if (action === "create") {
    const hasUrl = typeof input.url === "string" && input.url.length > 0;
    const hasUrls = Array.isArray(input.urls) && input.urls.length > 0;
    if (hasUrl && hasUrls) {
      return badInput(
        'watch create accepts either "url" (single) or "urls" (batch), not both',
        'Drop one of the fields \u2014 single URL \u2192 use "url" and read `{ job }` from the response; multiple \u2192 use "urls" and read `{ jobs }`.'
      );
    }
    if (!hasUrl && !hasUrls) return missing("url", "create");
    if (typeof input.interval_seconds !== "number" || !Number.isFinite(input.interval_seconds)) {
      return missing("interval_seconds", "create");
    }
    if (input.interval_seconds < MIN_INTERVAL_SECONDS) {
      return badInput(
        `interval_seconds must be >= ${MIN_INTERVAL_SECONDS}`,
        "Raise interval_seconds to at least 60 to respect target-site rate limits."
      );
    }
    const notification = input.notification ?? "inline";
    if (notification !== "inline") {
      const webhookCheck = guardUrl(notification, "notification");
      if (!webhookCheck.ok) {
        return badInput(webhookCheck.reason, webhookCheck.hint);
      }
    }
    if (hasUrl) {
      const urlCheck = guardUrl(input.url, "url");
      if (!urlCheck.ok) {
        return badInput(urlCheck.reason, urlCheck.hint);
      }
      const job = createJob({
        url: urlCheck.url.toString(),
        intervalSeconds: input.interval_seconds,
        selector: input.selector,
        notification
      });
      return { ok: true, data: { job, jobs: [job] } };
    }
    const urls = input.urls;
    if (urls.length > MAX_WATCH_BATCH_SIZE) {
      return badInput(
        `watch create batch exceeds limit (${urls.length} > ${MAX_WATCH_BATCH_SIZE})`,
        `Split the batch into chunks of at most ${MAX_WATCH_BATCH_SIZE} URLs.`
      );
    }
    const guarded = [];
    for (const u of urls) {
      const g = guardUrl(u, "url");
      if (!g.ok) {
        return badInput(g.reason, g.hint);
      }
      guarded.push(g);
    }
    const created = guarded.map((g) => {
      if (!g.ok) throw new Error("unreachable \u2014 pre-validated above");
      return createJob({
        url: g.url.toString(),
        intervalSeconds: input.interval_seconds,
        selector: input.selector,
        notification
      });
    });
    return { ok: true, data: { jobs: created } };
  }
  if (action === "check") {
    if (!input.job_id) return missing("job_id", "check");
    const job = getJob(input.job_id);
    if (!job) {
      return badInput(`watch job not found: ${input.job_id}`, "Run action=list to enumerate known job_ids.");
    }
    const report = await runCheck(job, router);
    const after = getJob(job.id) ?? job;
    const data = { jobs: [after], changes_since_last: [report] };
    return { ok: true, data };
  }
  if (action === "pause" || action === "resume") {
    if (!input.job_id) return missing("job_id", action);
    const next = setJobStatus(input.job_id, action === "pause" ? "paused" : "active");
    if (!next) {
      return badInput(`watch job not found: ${input.job_id}`, "Run action=list to enumerate known job_ids.");
    }
    return { ok: true, data: { jobs: [next] } };
  }
  if (action === "delete") {
    if (!input.job_id) return missing("job_id", "delete");
    const before = getJob(input.job_id);
    if (!before) {
      return badInput(`watch job not found: ${input.job_id}`, "Run action=list to enumerate known job_ids.");
    }
    deleteJob(input.job_id);
    log.debug("watch job removed", { id: input.job_id });
    return { ok: true, data: { jobs: [before] } };
  }
  return badInput(`unknown watch action: ${String(action)}`, "Use one of: create | list | check | pause | resume | delete.");
}
function _emptyChangeReport(url) {
  return { url, changed: false };
}
export {
  _emptyChangeReport,
  handleWatch
};
//# sourceMappingURL=watch.js.map