import {
  createPrivateKey,
  createPublicKey,
  generateKeyPairSync,
  randomBytes,
  sign,
  verify,
} from "node:crypto";

export const LICENSE_PREFIX = "MB1";
export const LICENSE_PRODUCT = "mobai-desktop";

export function normalizeMachineCode(value) {
  return String(value || "").replace(/[^a-fA-F0-9]/g, "").toUpperCase();
}

export function createKeyMaterial() {
  const { privateKey, publicKey } = generateKeyPairSync("ed25519");
  const jwk = publicKey.export({ format: "jwk" });
  return {
    privateKeyPem: privateKey.export({ type: "pkcs8", format: "pem" }),
    publicKeyRaw: jwk.x,
  };
}

export function publicKeyFromPrivate(privateKeyPem) {
  const privateKey = createPrivateKey(privateKeyPem);
  const jwk = createPublicKey(privateKey).export({ format: "jwk" });
  return jwk.x;
}

export function issueLicense({ privateKeyPem, machineCode, days = 365, expiresAt, note = "", now = Date.now() }) {
  const normalizedMachine = normalizeMachineCode(machineCode);
  if (!/^[A-F0-9]{16,64}$/.test(normalizedMachine)) {
    throw new Error("机器码格式不正确");
  }
  const normalizedDays = Number(days);
  if (!Number.isInteger(normalizedDays) || normalizedDays < 0 || normalizedDays > 3650) {
    throw new Error("有效期应为 0 到 3650 天；0 表示永久");
  }
  const issuedAt = Math.floor(now / 1000);
  let expiration;
  if (expiresAt !== undefined && expiresAt !== null && expiresAt !== "") {
    expiration = Math.floor(new Date(expiresAt).getTime() / 1000);
    if (!Number.isFinite(expiration) || expiration <= issuedAt || expiration > issuedAt + 3650 * 86400) {
      throw new Error("自定义到期时间应晚于现在，且不超过 10 年");
    }
  } else {
    expiration = normalizedDays === 0 ? 0 : issuedAt + normalizedDays * 86400;
  }
  const payload = {
    v: 1,
    product: LICENSE_PRODUCT,
    license_id: randomBytes(8).toString("hex").toUpperCase(),
    machine_code: normalizedMachine,
    issued_at: issuedAt,
    expires_at: expiration,
  };
  const payloadBytes = Buffer.from(JSON.stringify(payload));
  const signature = sign(null, payloadBytes, createPrivateKey(privateKeyPem));
  return {
    code: `${LICENSE_PREFIX}.${payloadBytes.toString("base64url")}.${signature.toString("base64url")}`,
    payload,
    note: String(note || "").trim().slice(0, 200),
  };
}

export function verifyLicense({ code, publicKeyRaw, machineCode, now = Date.now() }) {
  const parts = String(code || "").trim().split(".");
  if (parts.length !== 3 || parts[0] !== LICENSE_PREFIX) {
    return { valid: false, reason: "激活码格式不正确" };
  }
  try {
    const payloadBytes = Buffer.from(parts[1], "base64url");
    const signature = Buffer.from(parts[2], "base64url");
    const publicKey = createPublicKey({
      key: { kty: "OKP", crv: "Ed25519", x: publicKeyRaw },
      format: "jwk",
    });
    if (!verify(null, payloadBytes, publicKey, signature)) {
      return { valid: false, reason: "激活码签名不正确" };
    }
    const payload = JSON.parse(payloadBytes.toString("utf8"));
    if (payload.v !== 1 || payload.product !== LICENSE_PRODUCT) {
      return { valid: false, reason: "激活码产品信息不正确" };
    }
    if (normalizeMachineCode(payload.machine_code) !== normalizeMachineCode(machineCode)) {
      return { valid: false, reason: "激活码与当前机器不匹配" };
    }
    const current = Math.floor(now / 1000);
    if (payload.expires_at !== 0 && (!Number.isInteger(payload.expires_at) || payload.expires_at <= current)) {
      return { valid: false, reason: "激活码已到期" };
    }
    return { valid: true, payload };
  } catch {
    return { valid: false, reason: "激活码内容损坏" };
  }
}
