async function request(url, options = {}) {
  const response = await fetch(url, {
    ...options,
    headers: {
      "content-type": "application/json",
      ...(options.headers || {}),
    },
  });
  const data = await response.json().catch(() => ({}));
  if (!response.ok || (data && data.success === false)) {
    throw new Error(
      data?.error || `Запрос ${url} завершился ошибкой ${response.status}`,
    );
  }
  return data;
}

export const api = {
  state: () => request("/api/state"),
  config: () => request("/api/config"),

  rules: {
    get: () => request("/api/rules"),
    save: (rules) =>
      request("/api/rules", { method: "PUT", body: JSON.stringify({ rules }) }),
    conflicts: () => request("/api/rules/conflicts"),
  },

  deviceRules: {
    get: () => request("/api/device-rules"),
    save: (deviceRules) =>
      request("/api/device-rules", {
        method: "PUT",
        body: JSON.stringify({ deviceRules }),
      }),
  },

  devices: {
    get: () => request("/api/devices"),
    save: (devicesConfig) =>
      request("/api/devices", {
        method: "PUT",
        body: JSON.stringify(devicesConfig),
      }),
  },

  clientSettings: {
    get: () => request("/api/client-settings"),
    save: (clientSettings) =>
      request("/api/client-settings", {
        method: "PUT",
        body: JSON.stringify({ clientSettings }),
      }),
    checkSharedProxy: (url) =>
      request("/api/client-settings/shared-proxy/check", {
        method: "POST",
        body: JSON.stringify({ url }),
      }),
  },

  ruleSets: {
    get: () => request("/api/rule-sets"),
    save: (ruleSets) =>
      request("/api/rule-sets", {
        method: "PUT",
        body: JSON.stringify({ ruleSets }),
      }),
    lookup: (tag, url) =>
      request("/api/rule-sets/lookup", {
        method: "POST",
        body: JSON.stringify({ tag, url }),
      }),
    sagernetCatalog: () => request("/api/rule-sets/sagernet-catalog"),
  },

  subscription: {
    fetch: (url) =>
      request("/api/subscription/fetch", {
        method: "POST",
        body: JSON.stringify({ url }),
      }),
    forget: () => request("/api/subscription", { method: "DELETE" }),
  },

  apply: (selectedTag) =>
    request("/api/apply", {
      method: "POST",
      body: JSON.stringify({ selectedTag }),
    }),
  rollback: () => request("/api/apply/rollback", { method: "POST" }),

  singbox: {
    stop: () => request("/api/singbox/stop", { method: "POST" }),
    restart: () => request("/api/singbox/restart", { method: "POST" }),
    clear: () => request("/api/singbox/clear", { method: "POST" }),
  },

  servers: {
    ping: (host, port) =>
      request("/api/servers/ping", {
        method: "POST",
        body: JSON.stringify({ host, port }),
      }),
    pingAll: () => request("/api/servers/ping-all", { method: "POST" }),
  },

  bypass: (enabled) =>
    request("/api/bypass", {
      method: "POST",
      body: JSON.stringify({ enabled }),
    }),

  directCache: {
    get: () => request("/api/direct-cache"),
    flush: () => request("/api/direct-cache", { method: "DELETE" }),
  },

  route: {
    check: ({ host, ip, port, network, sourceIp, inbound }) =>
      request("/api/route/check", {
        method: "POST",
        body: JSON.stringify({ host, ip, port, network, sourceIp, inbound }),
      }),
  },

  configValidate: () => request("/api/config/validate", { method: "POST" }),
};
