#!/usr/bin/env node
/**
 * Scaffold Torbat Pay frontend module (MVP payment-14.0–14.5).
 * Run: node scripts/scaffold-payment-module.mjs
 */
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, "..");
const MOD = path.join(ROOT, "modules", "payment");
const APP = path.join(ROOT, "app", "payment");

function write(rel, content) {
  const full = path.isAbsolute(rel) ? rel : path.join(ROOT, rel);
  fs.mkdirSync(path.dirname(full), { recursive: true });
  fs.writeFileSync(full, content.replace(/\r\n/g, "\n"), "utf8");
  console.log("write", path.relative(ROOT, full));
}

const ROUTES = [
  { route: "hub", feature: "hub", title: "هاب تربت‌پی" },
  { route: "dashboard", feature: "dashboard", title: "داشبورد اجرایی" },
  { route: "overview", feature: "overview", title: "نمای کلی پرداخت" },
  { route: "kpis", feature: "kpis", title: "شاخص‌های کلیدی" },
  { route: "transactions", feature: "transactions", title: "تراکنش‌های اخیر" },
  { route: "transactions/[id]", feature: "transactionDetail", title: "جزئیات تراکنش" },
  { route: "ledger", feature: "ledger", title: "دفتر کل پرداخت" },
  { route: "psp", feature: "psp", title: "مدیریت درگاه‌ها" },
  { route: "psp/health", feature: "gatewayHealth", title: "سلامت درگاه" },
  { route: "providers", feature: "providers", title: "تخصیص ارائه‌دهنده" },
  { route: "merchants", feature: "merchants", title: "حساب‌های پذیرنده" },
  { route: "merchants/[id]", feature: "merchantDetail", title: "جزئیات پذیرنده" },
  { route: "merchants/approvals", feature: "merchantApprovals", title: "تأیید پذیرنده" },
  { route: "requests", feature: "requests", title: "درخواست‌های پرداخت" },
  { route: "requests/[id]", feature: "requestDetail", title: "جزئیات درخواست / چک‌اوت" },
  { route: "callbacks", feature: "callbacks", title: "مانیتور کال‌بک" },
  { route: "verification", feature: "verification", title: "مانیتور تأیید" },
  { route: "audit", feature: "audit", title: "لاگ حسابرسی" },
  { route: "bundles", feature: "bundles", title: "باندل‌ها" },
  { route: "feature-toggles", feature: "featureToggles", title: "کلیدهای ویژگی" },
  { route: "capabilities", feature: "capabilities", title: "قابلیت‌ها" },
  { route: "settings", feature: "settings", title: "تنظیمات پرداخت" },
  { route: "metrics", feature: "metrics", title: "متریک‌ها" },
  { route: "monitoring", feature: "monitoring", title: "مانیتورینگ" },
  { route: "api-explorer", feature: "apiExplorer", title: "کاوشگر API" },
  { route: "openapi", feature: "openapi", title: "مشاهده OpenAPI" },
];

// --- core module files ---
write("modules/payment/types/index.ts", `export type PaymentRecord = Record<string, unknown> & { id?: string; status?: string };

export type HealthResponse = { status: string; service: string; version: string };
export type CapabilitiesResponse = {
  service: string;
  version: string;
  phase: string;
  workspace_status?: string;
  default_payment_mode?: string;
  active_bundles?: string[];
  feature_toggles?: Record<string, boolean>;
  payment_sources_supported?: string[];
  payment_sources_reserved?: string[];
  contract_versions?: Record<string, string>;
};
export type MetricsResponse = {
  service: string;
  version: string;
  phase: string;
  metrics: Record<string, unknown>;
};
export type PermissionsCatalogResponse = { permissions: string[] };
`);

write("modules/payment/constants/permissions.ts", `export const PAYMENT_VIEW = "payment.view";
export const PAYMENT_MANAGE = "payment.manage";
export const PAYMENT_AUDIT_VIEW = "payment.audit.view";
export const PAYMENT_SETTINGS_MANAGE = "payment.settings.manage";
export const PAYMENT_PSP_VIEW = "payment.psp_connections.view";
export const PAYMENT_PSP_MANAGE = "payment.psp_connections.manage";
export const PAYMENT_MERCHANT_VIEW = "payment.merchant_accounts.view";
export const PAYMENT_MERCHANT_MANAGE = "payment.merchant_accounts.manage";
export const PAYMENT_REQUEST_VIEW = "payment.requests.view";
export const PAYMENT_REQUEST_CREATE = "payment.requests.create";
export const PAYMENT_TX_VIEW = "payment.transactions.view";
export const PAYMENT_LEDGER_VIEW = "payment.ledger.view";

export const ALL_PAYMENT_PERMISSIONS = [
  PAYMENT_VIEW,
  PAYMENT_MANAGE,
  PAYMENT_AUDIT_VIEW,
  PAYMENT_SETTINGS_MANAGE,
  PAYMENT_PSP_VIEW,
  PAYMENT_PSP_MANAGE,
  PAYMENT_MERCHANT_VIEW,
  PAYMENT_MERCHANT_MANAGE,
  PAYMENT_REQUEST_VIEW,
  PAYMENT_REQUEST_CREATE,
  PAYMENT_TX_VIEW,
  PAYMENT_LEDGER_VIEW,
] as const;
`);

write("modules/payment/constants/portals.ts", `import type { LucideIcon } from "lucide-react";
import {
  LayoutDashboard,
  CreditCard,
  Building2,
  Settings,
  Shield,
  Activity,
  BarChart3,
  Wallet,
  Plug,
  FileText,
  BookOpen,
  KeyRound,
  Gauge,
  ScrollText,
  Network,
  Eye,
} from "lucide-react";

export type PortalNavItem = { href: string; label: string; bundle?: string | null };
export type PortalNavGroup = {
  id: string;
  label: string;
  icon: LucideIcon;
  href?: string;
  bundle?: string | null;
  items?: PortalNavItem[];
};

export const PAYMENT_PORTAL = {
  id: "payment" as const,
  label: "تربت‌پی",
  description: "پلتفرم پرداخت سازمانی — BYO-PSP و پذیرنده",
  basePath: "/payment",
  icon: CreditCard,
};

export const PAYMENT_NAV: PortalNavGroup[] = [
  {
    id: "dashboards",
    label: "داشبوردها",
    icon: LayoutDashboard,
    items: [
      { href: "/payment/dashboard", label: "داشبورد اجرایی" },
      { href: "/payment/overview", label: "نمای کلی" },
      { href: "/payment/kpis", label: "شاخص‌های کلیدی" },
    ],
  },
  {
    id: "operations",
    label: "عملیات پرداخت",
    icon: Wallet,
    items: [
      { href: "/payment/requests", label: "درخواست‌های پرداخت" },
      { href: "/payment/transactions", label: "تراکنش‌ها" },
      { href: "/payment/ledger", label: "دفتر کل" },
      { href: "/payment/callbacks", label: "کال‌بک‌ها" },
      { href: "/payment/verification", label: "تأیید پرداخت" },
    ],
  },
  {
    id: "psp",
    label: "درگاه‌ها (PSP)",
    icon: Plug,
    bundle: "payment.byo_psp.basic",
    items: [
      { href: "/payment/psp", label: "مدیریت درگاه", bundle: "payment.byo_psp.basic" },
      { href: "/payment/psp/health", label: "سلامت درگاه", bundle: "payment.byo_psp.basic" },
      { href: "/payment/providers", label: "تخصیص ارائه‌دهنده" },
    ],
  },
  {
    id: "merchants",
    label: "پذیرندگان",
    icon: Building2,
    bundle: "payment.torbat_pay.merchant",
    items: [
      { href: "/payment/merchants", label: "حساب‌ها", bundle: "payment.torbat_pay.merchant" },
      { href: "/payment/merchants/approvals", label: "تأییدها", bundle: "payment.torbat_pay.merchant" },
    ],
  },
  {
    id: "licensing",
    label: "مجوز و باندل",
    icon: KeyRound,
    items: [
      { href: "/payment/bundles", label: "باندل‌ها" },
      { href: "/payment/feature-toggles", label: "کلیدهای ویژگی" },
      { href: "/payment/capabilities", label: "قابلیت‌ها" },
    ],
  },
  {
    id: "ops",
    label: "عملیات پلتفرم",
    icon: Activity,
    items: [
      { href: "/payment/monitoring", label: "مانیتورینگ" },
      { href: "/payment/metrics", label: "متریک‌ها" },
      { href: "/payment/audit", label: "حسابرسی" },
      { href: "/payment/settings", label: "تنظیمات" },
    ],
  },
  {
    id: "dev",
    label: "توسعه‌دهنده",
    icon: Network,
    items: [
      { href: "/payment/api-explorer", label: "کاوشگر API" },
      { href: "/payment/openapi", label: "OpenAPI" },
    ],
  },
];

export function navForPayment() {
  return PAYMENT_NAV;
}

export function filterNavByBundles(
  nav: PortalNavGroup[],
  activeBundles: string[] | undefined
) {
  const bundles = new Set(activeBundles ?? []);
  return nav
    .map((g) => {
      if (g.bundle && !bundles.has(g.bundle)) return null;
      const items = g.items?.filter((i) => !i.bundle || bundles.has(i.bundle));
      if (g.items && (!items || items.length === 0)) return null;
      return { ...g, items };
    })
    .filter(Boolean) as PortalNavGroup[];
}

export const MVP_ROUTE_HREFS = [
  "/payment/hub",
  "/payment/dashboard",
  "/payment/overview",
  "/payment/kpis",
  "/payment/transactions",
  "/payment/ledger",
  "/payment/psp",
  "/payment/psp/health",
  "/payment/providers",
  "/payment/merchants",
  "/payment/merchants/approvals",
  "/payment/requests",
  "/payment/callbacks",
  "/payment/verification",
  "/payment/audit",
  "/payment/bundles",
  "/payment/feature-toggles",
  "/payment/capabilities",
  "/payment/settings",
  "/payment/metrics",
  "/payment/monitoring",
  "/payment/api-explorer",
  "/payment/openapi",
] as const;
`);

write(
  "modules/payment/services/payment-api.ts",
  `/**
 * Torbat Pay API client — real backend only (MVP 14.0–14.5).
 * Browser → /api/payment BFF; SSR → direct upstream :8012
 */
import { getValidAccessToken, refreshSession } from "@/lib/auth";
import type {
  CapabilitiesResponse,
  HealthResponse,
  MetricsResponse,
  PaymentRecord,
  PermissionsCatalogResponse,
} from "@/modules/payment/types";

const PAYMENT_BASE =
  typeof window !== "undefined"
    ? "/api/payment"
    : process.env.PAYMENT_SERVICE_URL ||
      process.env.NEXT_PUBLIC_PAYMENT_API_URL ||
      "http://localhost:8012";

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

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

async function request<T>(path: string, options: RequestOptions): Promise<T> {
  const { tenantId, auth = true, idempotencyKey, 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 (idempotencyKey) headers.set("Idempotency-Key", idempotencyKey);
  if (auth) {
    const token = await getValidAccessToken();
    if (token) headers.set("Authorization", \`Bearer \${token}\`);
  }
  const url = path.startsWith("http")
    ? path
    : \`\${PAYMENT_BASE.replace(/\\/$/, "")}\${path.startsWith("/") ? path : \`/\${path}\`}\`;

  let res: Response;
  try {
    res = await fetch(url, { ...init, headers, cache: "no-store" });
  } catch (err) {
    const detail = err instanceof Error ? err.message : "network_error";
    throw new Error(\`اتصال به سرویس تربت‌پی برقرار نشد — \${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, cache: "no-store" });
    }
  }

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

function crud(basePath: string) {
  return {
    list: (tenantId: string) => request<PaymentRecord[]>(basePath, { tenantId }),
    get: (tenantId: string, id: string) => request<PaymentRecord>(\`\${basePath}/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<PaymentRecord>(basePath, { tenantId, method: "POST", body: JSON.stringify(body) }),
    update: (tenantId: string, id: string, body: Record<string, unknown>) =>
      request<PaymentRecord>(\`\${basePath}/\${id}\`, {
        tenantId,
        method: "PATCH",
        body: JSON.stringify(body),
      }),
  };
}

export const paymentApi = {
  health: (): Promise<HealthResponse> => fetch(\`\${PAYMENT_BASE}/health\`).then((r) => r.json()),
  capabilities: (tenantId: string) =>
    request<CapabilitiesResponse>("/capabilities", { tenantId }),
  metrics: (tenantId?: string) =>
    tenantId
      ? request<MetricsResponse>("/metrics", { tenantId })
      : fetch(\`\${PAYMENT_BASE}/metrics\`).then((r) => r.json()),
  openapi: async (): Promise<Record<string, unknown>> => {
    const r = await fetch(\`\${PAYMENT_BASE}/openapi.json\`);
    if (!r.ok) throw new PaymentApiError(r.status, "openapi_error", "OpenAPI در دسترس نیست");
    return r.json();
  },
  permissions: {
    catalog: (tenantId: string) =>
      request<PermissionsCatalogResponse>("/api/v1/permissions/catalog", { tenantId }),
  },
  audit: {
    list: (tenantId: string) => request<PaymentRecord[]>("/api/v1/audit", { tenantId }),
  },
  workspaces: crud("/api/v1/payment-workspaces"),
  bundleDefinitions: crud("/api/v1/bundle-definitions"),
  tenantBundles: crud("/api/v1/tenant-bundles"),
  featureToggles: crud("/api/v1/feature-toggles"),
  providerAssignments: crud("/api/v1/provider-assignments"),
  pspRegistrations: crud("/api/v1/psp-provider-registrations"),
  creditRegistrations: crud("/api/v1/credit-provider-registrations"),
  configurations: crud("/api/v1/configurations"),
  settings: crud("/api/v1/settings"),
  pspConnections: {
    ...crud("/api/v1/psp-connections"),
    test: (tenantId: string, id: string) =>
      request<Record<string, unknown>>(\`/api/v1/psp-connections/\${id}/test\`, {
        tenantId,
        method: "POST",
        body: "{}",
      }),
  },
  pspRouting: crud("/api/v1/psp-routing-policies"),
  merchants: {
    list: (tenantId: string) => request<PaymentRecord[]>("/api/v1/merchant-accounts", { tenantId }),
    get: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/merchant-accounts/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>) =>
      request<PaymentRecord>("/api/v1/merchant-accounts", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
      }),
    submit: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/merchant-accounts/\${id}/submit\`, { tenantId, method: "POST", body: "{}" }),
    activate: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/merchant-accounts/\${id}/activate\`, { tenantId, method: "POST", body: "{}" }),
    suspend: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/merchant-accounts/\${id}/suspend\`, { tenantId, method: "POST", body: "{}" }),
    close: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/merchant-accounts/\${id}/close\`, { tenantId, method: "POST", body: "{}" }),
  },
  settlementProfiles: crud("/api/v1/merchant-settlement-profiles"),
  requests: {
    list: (tenantId: string) => request<PaymentRecord[]>("/api/v1/payment-requests", { tenantId }),
    get: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/payment-requests/\${id}\`, { tenantId }),
    create: (tenantId: string, body: Record<string, unknown>, idempotencyKey: string) =>
      request<PaymentRecord>("/api/v1/payment-requests", {
        tenantId,
        method: "POST",
        body: JSON.stringify(body),
        idempotencyKey,
      }),
    cancel: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/payment-requests/\${id}/cancel\`, { tenantId, method: "POST", body: "{}" }),
    verify: (tenantId: string, id: string, body?: Record<string, unknown>) =>
      request<PaymentRecord>(\`/api/v1/payment-requests/\${id}/verify\`, {
        tenantId,
        method: "POST",
        body: JSON.stringify(body ?? { status: "paid" }),
      }),
  },
  transactions: {
    list: (tenantId: string) => request<PaymentRecord[]>("/api/v1/payment-transactions", { tenantId }),
    get: (tenantId: string, id: string) =>
      request<PaymentRecord>(\`/api/v1/payment-transactions/\${id}\`, { tenantId }),
    bySource: (tenantId: string, service?: string, refId?: string) => {
      const sp = new URLSearchParams();
      if (service) sp.set("service", service);
      if (refId) sp.set("ref_id", refId);
      const q = sp.toString();
      return request<PaymentRecord[]>(\`/api/v1/payment-transactions/by-source\${q ? \`?\${q}\` : ""}\`, {
        tenantId,
      });
    },
  },
  ledger: {
    list: (tenantId: string) => request<PaymentRecord[]>("/api/v1/payment-ledger-entries", { tenantId }),
  },
};

export const PAYMENT_API_CATALOG = [
  { method: "GET", path: "/health", phase: "14.0" },
  { method: "GET", path: "/capabilities", phase: "14.0" },
  { method: "GET", path: "/metrics", phase: "14.0" },
  { method: "GET|POST", path: "/api/v1/payment-workspaces", phase: "14.0" },
  { method: "GET|POST", path: "/api/v1/tenant-bundles", phase: "14.0" },
  { method: "GET|POST", path: "/api/v1/feature-toggles", phase: "14.0" },
  { method: "GET|POST", path: "/api/v1/psp-connections", phase: "14.1" },
  { method: "POST", path: "/api/v1/psp-connections/{id}/test", phase: "14.1" },
  { method: "GET|POST", path: "/api/v1/merchant-accounts", phase: "14.2" },
  { method: "POST", path: "/api/v1/payment-requests", phase: "14.3" },
  { method: "POST", path: "/api/v1/payment-requests/{id}/verify", phase: "14.4" },
  { method: "GET", path: "/api/v1/payment-transactions", phase: "14.5" },
  { method: "GET", path: "/api/v1/payment-ledger-entries", phase: "14.5" },
] as const;
`
);
