/**
 * 页面机器标签编解码（与组件文件名刻意区分，避免 Windows 大小写冲突）。
 * 解码：decodeAjzMachinePayload
 */

export const AJZ_MACHINE_PREFIX = "AJZP1";
export const AJZ_MACHINE_MIME = "application/x-ajz-machine";

/** 与源码绑定的混淆钥（非安全加密；仅避免 DOM 明文接口）。 */
const OBFUSCATION_KEY = "aijianzhan-page-machine-v1";

export type PageMachineManifest = {
  v: 1;
  kind: "ajz-page";
  slug: string;
  base_path: string;
  page: {
    id: string;
    type: string;
    route: string;
    title: string;
  };
  entity: string;
  resource: string;
  auth: { type: "bearer_jwt"; header: "Authorization" };
  endpoints: Record<string, { method: string; path: string }>;
  filters?: string[];
  fields?: { name: string; type: string; label?: string }[];
  actions?: string[];
  widgets?: { type: string; title?: string; entity?: string }[];
  notes?: string;
};

function xorBytes(data: Uint8Array, key: string): Uint8Array {
  const out = new Uint8Array(data.length);
  const kb = new TextEncoder().encode(key);
  for (let i = 0; i < data.length; i++) {
    out[i] = data[i] ^ kb[i % kb.length];
  }
  return out;
}

function bytesToB64Url(bytes: Uint8Array): string {
  let bin = "";
  for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);
  return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

function b64UrlToBytes(s: string): Uint8Array {
  const pad = s.length % 4 === 0 ? "" : "=".repeat(4 - (s.length % 4));
  const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + pad;
  const bin = atob(b64);
  const out = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
  return out;
}

/** 编码为 AJZP1.<payload>（非明文 JSON）。 */
export function encodeAjzMachinePayload(manifest: object): string {
  const raw = new TextEncoder().encode(JSON.stringify(manifest));
  const xored = xorBytes(raw, OBFUSCATION_KEY);
  return `${AJZ_MACHINE_PREFIX}.${bytesToB64Url(xored)}`;
}

/** 供 AI/脚本解析页面时解码。 */
export function decodeAjzMachinePayload<T = PageMachineManifest>(token: string): T {
  const t = (token || "").trim();
  const prefix = `${AJZ_MACHINE_PREFIX}.`;
  if (!t.startsWith(prefix)) {
    throw new Error("invalid ajz machine payload");
  }
  const xored = b64UrlToBytes(t.slice(prefix.length));
  const raw = xorBytes(xored, OBFUSCATION_KEY);
  return JSON.parse(new TextDecoder().decode(raw)) as T;
}

export function buildPageMachineManifest(input: {
  slug: string;
  page: { id: string; type: string; route: string; title: string; entity: string; layout?: any };
  resource: string;
  blueprint: any;
}): PageMachineManifest {
  const { slug, page, resource, blueprint } = input;
  const base = `/api/v1/apps/${slug}`;
  const root = `${base}/${resource}`;
  const resMeta =
    (blueprint?.apis?.resources || []).find((x: any) => x.entity === page.entity) ||
    (blueprint?.apis?.resources || []).find(
      (x: any) => String(x.path || "").replace(/^\//, "") === resource
    );
  const ops: string[] = resMeta?.operations || [
    "list",
    "get",
    "create",
    "update",
    "delete",
    "import",
    "export",
  ];
  const endpoints: PageMachineManifest["endpoints"] = {};
  if (ops.includes("list")) endpoints.list = { method: "GET", path: root };
  if (ops.includes("get")) endpoints.get = { method: "GET", path: `${root}/{id}` };
  if (ops.includes("create")) endpoints.create = { method: "POST", path: root };
  if (ops.includes("update")) endpoints.update = { method: "PUT", path: `${root}/{id}` };
  if (ops.includes("delete")) endpoints.delete = { method: "DELETE", path: `${root}/{id}` };
  if (ops.includes("import")) endpoints.import = { method: "POST", path: `${root}/import` };
  if (ops.includes("export")) endpoints.export = { method: "GET", path: `${root}/export` };
  endpoints.aggregate = { method: "GET", path: `${root}/aggregate` };
  endpoints.blueprint = { method: "GET", path: `${base}/blueprint` };

  const ent = (blueprint?.entities || []).find((e: any) => e.name === page.entity);
  const fields = (ent?.fields || [])
    .filter((f: any) => f?.name)
    .slice(0, 80)
    .map((f: any) => ({
      name: String(f.name),
      type: String(f.type || "string"),
      label: f.label ? String(f.label) : undefined,
    }));

  return {
    v: 1,
    kind: "ajz-page",
    slug,
    base_path: base,
    page: {
      id: page.id,
      type: page.type,
      route: page.route || "",
      title: page.title || "",
    },
    entity: page.entity,
    resource,
    auth: { type: "bearer_jwt", header: "Authorization" },
    endpoints,
    filters: page.layout?.filters || resMeta?.list?.allowed_filters || [],
    fields,
    actions: page.layout?.actions || [],
    widgets: (page.layout?.widgets || []).map((w: any) => ({
      type: w.type,
      title: w.title,
      entity: w.entity,
    })),
    notes: "list 支持 filter.<field>=value；需 Authorization: Bearer <jwt>",
  };
}
