#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");

const RESOURCES = [
  ["venues", true, true],
  ["branches", true, true],
  ["dining-areas", false, false],
  ["tables", false, false],
  ["menus", true, true],
  ["menu-categories", false, false],
  ["menu-items", false, false],
  ["allergens", false, false],
  ["modifier-groups", false, false],
  ["modifier-options", false, false],
  ["availability-windows", false, false],
  ["menu-media-refs", false, false],
  ["qr-codes", false, false],
  ["qr-menu-sessions", false, false],
  ["carts", false, false],
  ["cart-lines", false, false],
  ["pos-registers", false, false],
  ["pos-ticket-lines", false, false],
  ["pos-payments", false, false],
  ["pos-discounts", false, false],
  ["pos-tax-lines", false, false],
  ["pos-floor-plans", false, false],
  ["pos-stations", false, false],
  ["kitchen-stations", false, false],
  ["connector-registrations", false, false],
  ["connector-dispatches", false, false],
  ["analytics-reports", false, false],
  ["bundle-definitions", false, false],
  ["roles", false, false],
  ["permissions", false, false],
  ["configurations", true, false],
  ["events", false, false],
];

function kebabToProp(s) {
  return s.split("-").map((p, i) => (i === 0 ? p : p[0].toUpperCase() + p.slice(1))).join("");
}

let apiBlocks = "";
for (const [p, hasUpdate, hasDelete] of RESOURCES) {
  const prop = kebabToProp(p);
  let block = `  ${prop}: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/${p}\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/${p}/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(\`/api/v1/${p}\`, {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),`;
  if (hasUpdate) {
    block += `
    update: (tenantId: string, id: string, body: Record<string, unknown>) =>
      request<Record<string, unknown>>(\`/api/v1/${p}/\${id}\`, {
        tenantId,
        method: "PATCH",
        body: JSON.stringify(body),
      }),`;
  }
  if (hasDelete) {
    block += `
    remove: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/${p}/\${id}/delete\`, { tenantId, method: "POST" }),`;
  }
  block += `
  },`;
  apiBlocks += block + "\n";
}

const header = `/**
 * Hospitality Service API client — Torbat Food (real backend only).
 * Browser → /api/hospitality BFF; SSR → direct upstream :8009
 */

import { getValidAccessToken, refreshSession } from "@/lib/auth";
import type { CapabilitiesResponse, HealthResponse, ListParams } from "@/modules/hospitality/types";

const HOSPITALITY_BASE =
  typeof window !== "undefined"
    ? "/api/hospitality"
    : process.env.HOSPITALITY_SERVICE_URL ||
      process.env.NEXT_PUBLIC_HOSPITALITY_API_URL ||
      "http://localhost:8009";

export class HospitalityApiError extends Error {
  constructor(
    public status: number,
    public code: string,
    message: string
  ) {
    super(message);
    this.name = "HospitalityApiError";
  }
}

type RequestOptions = RequestInit & { tenantId: string; auth?: boolean };

async function request<T>(path: string, options: RequestOptions): Promise<T> {
  const { tenantId, auth = true, headers: customHeaders, ...init } = options;
  const headers = new Headers(customHeaders);
  if (!headers.has("Content-Type") && init.body) {
    headers.set("Content-Type", "application/json");
  }
  headers.set("X-Tenant-ID", tenantId);
  if (auth) {
    const token = await getValidAccessToken();
    if (token) headers.set("Authorization", \`Bearer \${token}\`);
  }

  const url = path.startsWith("http")
    ? path
    : \`\${HOSPITALITY_BASE.replace(/\\/$/, "")}\${path.startsWith("/") ? path : \`/\${path}\`}\`;

  let res: Response;
  try {
    res = await fetch(url, { ...init, headers });
  } catch (err) {
    const detail = err instanceof Error ? err.message : "network_error";
    throw new Error(\`اتصال به سرویس تربت فود برقرار نشد (\${url}) — \${detail}\`);
  }

  if (res.status === 401 && auth) {
    const refreshed = await refreshSession({ force: true });
    if (refreshed) {
      headers.set("Authorization", \`Bearer \${refreshed}\`);
      res = await fetch(url, { ...init, headers });
    }
  }

  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    throw new HospitalityApiError(
      res.status,
      body?.error?.code || body?.detail || "unknown_error",
      body?.error?.message || body?.detail || res.statusText
    );
  }
  if (res.status === 204) return undefined as T;
  return res.json() as Promise<T>;
}

function qs(params?: Record<string, string | number | undefined | null>) {
  if (!params) return "";
  const sp = new URLSearchParams();
  Object.entries(params).forEach(([k, v]) => {
    if (v !== undefined && v !== null && v !== "") sp.set(k, String(v));
  });
  const s = sp.toString();
  return s ? \`?\${s}\` : "";
}

function action(tenantId: string, apiPath: string, body?: Record<string, unknown>) {
  return request<Record<string, unknown>>(apiPath, {
    tenantId,
    method: "POST",
    body: body ? JSON.stringify(body) : undefined,
  });
}

export const hospitalityApi = {
  health: (): Promise<HealthResponse> =>
    fetch(\`\${HOSPITALITY_BASE}/health\`).then((r) => r.json()),

  capabilities: (): Promise<CapabilitiesResponse> =>
    fetch(\`\${HOSPITALITY_BASE}/capabilities\`).then((r) => r.json()),

${apiBlocks}
  tenantBundles: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/tenant-bundles\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/tenant-bundles/\${id}\`, { tenantId }),
    activate: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/tenant-bundles/activate", body),
    deactivate: (tenantId: string, id: string) =>
      action(tenantId, \`/api/v1/tenant-bundles/\${id}/deactivate\`),
  },
  featureToggles: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/feature-toggles\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/feature-toggles/\${id}\`, { tenantId }),
    upsert: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/feature-toggles/upsert", body),
  },
  menuItemModifiers: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/menu-item-modifiers\${qs(params)}\`, { tenantId }),
    link: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/menu-item-modifiers/link", body),
  },
  menuItemAllergens: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/menu-item-allergens\${qs(params)}\`, { tenantId }),
    link: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/menu-item-allergens/link", body),
  },
  menuLocalizations: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/menu-localizations\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/menu-localizations/\${id}\`, { tenantId }),
    upsert: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/menu-localizations/upsert", body),
  },
  settings: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/settings\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/settings/\${id}\`, { tenantId }),
    upsert: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/settings/upsert", body),
  },
  reservations: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/reservations\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/reservations/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/reservations", body),
    updateStatus: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, \`/api/v1/reservations/\${id}/status\`, body),
  },
  tableAssignments: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/table-assignments\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/table-assignments/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/table-assignments", body),
    release: (tenantId: string, id: string) =>
      action(tenantId, \`/api/v1/table-assignments/\${id}/release\`),
  },
  serviceRequests: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/service-requests\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/service-requests/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/service-requests", body),
    updateStatus: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, \`/api/v1/service-requests/\${id}/status\`, body),
  },
  waitlist: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/waitlist\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/waitlist/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/waitlist", body),
    updateStatus: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, \`/api/v1/waitlist/\${id}/status\`, body),
  },
  posShifts: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/pos-shifts\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/pos-shifts/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/pos-shifts", body),
    close: (tenantId: string, id: string) =>
      action(tenantId, \`/api/v1/pos-shifts/\${id}/close\`),
  },
  posTickets: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/pos-tickets\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/pos-tickets/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/pos-tickets", body),
    void: (tenantId: string, id: string) =>
      action(tenantId, \`/api/v1/pos-tickets/\${id}/void\`),
  },
  qrOrderingSessions: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/qr-ordering-sessions\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/qr-ordering-sessions/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/qr-ordering-sessions", body),
    submit: (tenantId: string, id: string) =>
      action(tenantId, \`/api/v1/qr-ordering-sessions/\${id}/submit\`),
  },
  kitchenTickets: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/kitchen-tickets\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/kitchen-tickets/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/kitchen-tickets", body),
    updateStatus: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, \`/api/v1/kitchen-tickets/\${id}/status\`, body),
  },
  kitchenTicketItems: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/kitchen-ticket-items\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/kitchen-ticket-items/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/kitchen-ticket-items", body),
    updateStatus: (tenantId: string, id: string, body: Record<string, unknown>) =>
      action(tenantId, \`/api/v1/kitchen-ticket-items/\${id}/status\`, body),
  },
  analyticsSnapshots: {
    list: (tenantId: string, params?: ListParams) =>
      request<Record<string, unknown>[]>(\`/api/v1/analytics-snapshots\${qs(params)}\`, { tenantId }),
    get: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/analytics-snapshots/\${id}\`, { tenantId }),
    refresh: (tenantId: string, body: Record<string, unknown>) =>
      action(tenantId, "/api/v1/analytics-snapshots/refresh", body),
  },
};
`;

fs.writeFileSync(path.join(ROOT, "modules/hospitality/services/hospitality-api.ts"), header);
console.log("Generated hospitality-api.ts");
