// Generated by bynkc — do not edit by hand.
// context shop.payment

import { Ok, Err, Some, None, type Result, type Option, type ValidationError, type JsonValue, type BoundaryError, type ServiceBinding, callService, boundaryError } from "../../runtime.js";

export type PayError =
    { readonly tag: "Declined" };

export const PayError = {
  Declined: { tag: "Declined" } as PayError,
};

export interface Bank {
  charge(cents: number): Promise<Result<number, PayError>>;
}

export const BankToken: unique symbol = Symbol("Bank");

export class StubBank implements Bank {
  async charge(cents: number): Promise<Result<number, PayError>> {
    return (cents > 10000 ? Err(PayError.Declined) : Ok(cents));
  }
}

export const StubBankProvider = { token: BankToken, factory: () => new StubBank() };

export const authorise = {
  async call(cents: number, deps: { Bank: Bank }): Promise<Result<number, PayError>> {
    const r = await deps.Bank.charge(cents);
    return r;
  },
};

export function serialise_PayError(value: PayError): JsonValue {
  switch (value.tag) {
    case "Declined":
      return { kind: "Declined" };
  }
}

export function deserialise_PayError(json: JsonValue, path: string = "$"): Result<PayError, BoundaryError> {
  if (typeof json !== "object" || json === null || Array.isArray(json)) {
    return Err({ kind: "StructuralMismatch", path, expected: "object", actual: typeof json });
  }
  const obj = json as { [k: string]: JsonValue };
  const kind = obj["kind"];
  switch (kind) {
    case "Declined":
      return Ok({ tag: "Declined" } as PayError);
    default:
      return Err({ kind: "StructuralMismatch", path, expected: "sum variant kind", actual: String(kind) });
  }
}


export function serialise_Result_Int_PayError(value: Result<number, PayError>): JsonValue {
  if (value.tag === "Ok") return { kind: "Ok", value: value.value as JsonValue };
  return { kind: "Err", error: serialise_PayError(value.error) };
}

export function deserialise_Result_Int_PayError(json: JsonValue, path: string = "$"): Result<Result<number, PayError>, BoundaryError> {
  if (typeof json !== "object" || json === null || Array.isArray(json)) {
    return Err({ kind: "StructuralMismatch", path, expected: "object", actual: typeof json });
  }
  const obj = json as { [k: string]: JsonValue };
  if (obj["kind"] === "Ok") {
  if (typeof obj["value"] !== "number") {
    return Err({ kind: "StructuralMismatch", path: `${path}.value`, expected: "number", actual: typeof obj["value"] });
  }
  if (!Number.isInteger(obj["value"])) {
    return Err({ kind: "StructuralMismatch", path: `${path}.value`, expected: "integer", actual: String(obj["value"]) });
  }
  const __v = obj["value"];
    return Ok(Ok(__v) as Result<number, PayError>);
  } else if (obj["kind"] === "Err") {
  const __r_e = deserialise_PayError(obj["error"], `${path}.error`);
  if (__r_e.tag === "Err") return __r_e;
  const __e = __r_e.value;
    return Ok(Err(__e) as Result<number, PayError>);
  }
  return Err({ kind: "StructuralMismatch", path, expected: "Ok | Err", actual: String(obj["kind"]) });
}

