export {};

declare global {
  type TiketoWhereAmIInput = Record<string, never>;
  type TiketoWhereAmIOutput = {
    "route": string;
  };
  type TiketoSetFeatureInput = {
    "feature": "darkMode" | "highlight";
    "enabled": boolean;
  };
  type TiketoSetFeatureOutput = {
    "feature": "darkMode" | "highlight";
    "enabled": boolean;
  };

  type TiketoConfirmPayload = {
    "requestId": string;
    "question": string;
    "fallbackText"?: string;
  };
  type TiketoConfirmReply = {
    "requestId": string;
    "value": "yes" | "no";
  };
  type TiketoChoicePayload = {
    "requestId": string;
    "prompt": string;
    "options": Array<{
      "value": string;
      "label": string;
    }>;
    "fallbackText"?: string;
  };
  type TiketoChoiceReply = {
    "requestId": string;
    "value": string;
  };
  type TiketoCardPayload = {
    "title": string;
    "text": string;
    "imageUrl"?: string;
    "link"?: {
      "url": string;
      "label": string;
    };
    "fallbackText"?: string;
  };
  type TiketoCardReply = null;
  type TiketoProductPreviewPayload = {
    "requestId": string;
    "productId": string;
    "name": string;
    "price": number;
    "currency": "CZK" | "EUR";
    "imageUrl"?: string;
    "variants": Array<string>;
    "fallbackText"?: string;
  };
  type TiketoProductPreviewReply = {
    "requestId": string;
    "productId": string;
    "variant": string;
  };

  interface TiketoHostActions {
    "whereAmI": { input: TiketoWhereAmIInput; output: TiketoWhereAmIOutput };
    "setFeature": { input: TiketoSetFeatureInput; output: TiketoSetFeatureOutput };
  }

  interface TiketoHostComponents {
    "productPreview": { payload: TiketoProductPreviewPayload; reply: TiketoProductPreviewReply };
  }

  type TiketoActionHandler<Name extends keyof TiketoHostActions> = (
    payload: TiketoHostActions[Name]["input"],
  ) => TiketoHostActions[Name]["output"] | Promise<TiketoHostActions[Name]["output"]>;

  type TiketoComponentAPI<Name extends keyof TiketoHostComponents> = {
    reply(value: TiketoHostComponents[Name]["reply"]): void;
  };

  type TiketoComponentRenderer<Name extends keyof TiketoHostComponents> = (
    element: HTMLElement,
    payload: TiketoHostComponents[Name]["payload"],
    api: TiketoComponentAPI<Name>,
  ) => void | (() => void);

  type TiketoResetOptions = {
    relaunch?: boolean;
  };

  type TiketoChatErrorCode = "config_failed" | "widget_failed" | "init_failed" | "reset_failed" | "relaunch_failed";

  interface TiketoChatError extends Error {
    readonly name: "TiketoChatError";
    readonly code: TiketoChatErrorCode;
    readonly cause: Error;
  }

  interface TiketoChat {
    (command: "init", clientID: `TC-${string}`): void;
    (command: "context", values: Record<string, unknown>): void;
    /** @since 0.3.0 */
    (command: "on", event: "ready", handler: () => void): void;
    /** @since 0.3.0 */
    (command: "on", event: "error", handler: (error: TiketoChatError) => void): void;
    /** @since 0.3.0 */
    (command: "off", event: "ready", handler: () => void): void;
    /** @since 0.3.0 */
    (command: "off", event: "error", handler: (error: TiketoChatError) => void): void;
    /** @since 0.3.0 */
    (command: "reset", options?: TiketoResetOptions): Promise<void>;
    <Name extends keyof TiketoHostActions>(command: "action", name: Name, handler: TiketoActionHandler<Name>): void;
    <Name extends string>(command: "action", name: Name extends keyof TiketoHostActions ? never : Name, handler: (payload: Record<string, unknown>) => unknown | Promise<unknown>): void;
    <Name extends keyof TiketoHostComponents>(command: "component", name: Name, renderer: TiketoComponentRenderer<Name>): void;
    <Name extends string>(command: "component", name: Name extends keyof TiketoHostComponents ? never : Name, renderer: (element: HTMLElement, payload: Record<string, unknown>, api: { reply(value: unknown): void }) => void | (() => void)): void;
    q?: IArguments[];
  }

  var tiketoChat: TiketoChat;
  interface Window { tiketoChat: TiketoChat }
}
