const tabs = new Set(["timeline", "findings", "diagnostics"]);
const statuses = new Set(["", "succeeded", "failed", "blocked", "running", "unknown"]);

export function readMonitorRoute(input = window.location.href) {
  try {
    const url = new URL(input, window.location.origin);
    const tab = url.searchParams.get("tab") || "timeline";
    const status = url.searchParams.get("status") || "";
    const from = url.searchParams.get("from") || "";
    const to = url.searchParams.get("to") || "";
    if (!tabs.has(tab)) return invalid("invalid_tab");
    if (!statuses.has(status)) return invalid("invalid_status");
    if (!validDate(from) || !validDate(to)) return invalid("invalid_time_range");
    if (from && to && Date.parse(from) > Date.parse(to)) return invalid("invalid_time_range");
    const segments = url.pathname.split("/").filter(Boolean);
    if (segments[0] !== "monitor") return invalid("unsupported_path");
    const route = { kind: "workspace", runId: "", detailType: "", detailId: "", tab, filters: { sentinelId: value(url, "sentinelId"), node: value(url, "node"), lane: value(url, "lane"), status, from, to } };
    if (segments.length === 1) return route;
    if (segments[1] !== "runs" || !segments[2]) return invalid("unsupported_path");
    route.kind = "run";
    route.runId = decodeURIComponent(segments[2]);
    if (segments.length === 3) return route;
    const detailTypes = { findings: "finding", events: "event", artifacts: "artifact", diagnostics: "diagnostic" };
    if (!detailTypes[segments[3]] || !segments[4] || segments.length !== 5) return invalid("unsupported_path");
    route.kind = "detail";
    route.detailType = detailTypes[segments[3]];
    route.detailId = decodeURIComponent(segments[4]);
    return route;
  } catch {
    return invalid("malformed_url_encoding");
  }
}

export function monitorRouteHref(route) {
  const path = route.runId ? `/monitor/runs/${encodeURIComponent(route.runId)}${detailPath(route)}` : "/monitor";
  const url = new URL(path, window.location.origin);
  for (const [key, item] of Object.entries(route.filters || {})) if (item) url.searchParams.set(key, item);
  if (route.tab && route.tab !== "timeline") url.searchParams.set("tab", route.tab);
  return `${url.pathname}${url.search}`;
}

export function withMonitorRoute(route, patch) { return { ...route, ...patch, filters: { ...route.filters, ...(patch.filters || {}) } }; }
function invalid(reason) { return { kind: "invalid", reason }; }
function value(url, key) { return url.searchParams.get(key) || ""; }
function validDate(value) { return !value || Number.isFinite(Date.parse(value)); }
function detailPath(route) { const segments = { finding: "findings", event: "events", artifact: "artifacts", diagnostic: "diagnostics" }; return route.detailType && route.detailId ? `/${segments[route.detailType]}/${encodeURIComponent(route.detailId)}` : ""; }
