import { expect, test } from "bun:test";
import {
  localizeDescriptor,
  openApiRequestBody,
  parseDescriptor,
  toJsonSchema,
  v,
} from "../src/index.ts";

const contact = v.object({
  email: v.string().trim().email().label("Email address"),
  age: v.number().integer().min(18),
  role: v
    .string()
    .oneOf(["user", "admin"] as const)
    .optional(),
});

test("exports standards-compatible JSON Schema and OpenAPI request bodies", () => {
  expect(toJsonSchema(contact, { id: "urn:wrn:contact", title: "Contact" })).toEqual({
    $schema: "https://json-schema.org/draft/2020-12/schema",
    $id: "urn:wrn:contact",
    title: "Contact",
    type: "object",
    properties: {
      email: { type: "string", title: "Email address", "x-wrn-trim": true, format: "email" },
      age: { type: "integer", minimum: 18 },
      role: { type: "string", enum: ["user", "admin"] },
    },
    required: ["email", "age"],
    additionalProperties: false,
  });
  const body = openApiRequestBody(contact, {
    description: "Contact input",
    contentTypes: ["application/json", "application/x-www-form-urlencoded"],
  });
  expect(body.required).toBe(true);
  expect(Object.keys(body.content)).toEqual([
    "application/json",
    "application/x-www-form-urlencoded",
  ]);
});

test("localized descriptors produce the same server/browser-ready errors", () => {
  const messages: Record<string, string> = {
    required: "{label} आवश्यक आहे",
    number: "{label} संख्या असणे आवश्यक आहे",
    "rule.email": "वैध ईमेल द्या",
    "rule.integer": "पूर्णांक द्या",
    "rule.min": "किमान {n}",
    "rule.oneOf": "परवानगी असलेले मूल्य द्या",
  };
  const descriptor = localizeDescriptor(contact, (key, params) =>
    (messages[key] ?? key).replace(/\{(\w+)\}/g, (_, name) => String(params[name] ?? "")),
  );
  expect(parseDescriptor(descriptor, { email: "bad", age: "nope" }).errors).toEqual({
    email: "वैध ईमेल द्या",
    age: "age संख्या असणे आवश्यक आहे",
  });
  expect(parseDescriptor(descriptor, {}).errors.email).toBe("Email address आवश्यक आहे");
});
