/**
 * Load after <button id="connect-btn" type="button">Connect channel</button>
 * and <button id="cancel-btn" type="button" disabled>Cancel authorization</button>
 * and <p id="status" role="status"></p>.
 * Negative results resolve; technical SDK errors reject. Neither is logged.
 * AbortSignal support is an Unreleased change; see the repository changelog.
 */
import Omnizapi, { OmnizapiError } from "@omnizapi/connect";
import type { ConnectionFailureReason, OmnizapiClient, OmnizapiErrorCode } from "@omnizapi/connect";

const failureMessages: Record<ConnectionFailureReason, string> = {
  cancelled: "Authorization was cancelled.",
  popup_closed: "The popup was closed before authorization finished.",
  not_completed: "Authorization was not completed.",
  invalid_channel: "This channel is invalid or unavailable.",
  origin_not_allowed: "This application origin is not authorized for the channel.",
  unsupported_channel: "This channel type is not supported.",
};

const errorMessages: Record<OmnizapiErrorCode, string> = {
  BROWSER_REQUIRED: "Open this page in a browser to connect.",
  CONNECTION_IN_PROGRESS: "Finish the active attempt. If native Meta login is still awaiting its callback, wait for it or reload before another native attempt.",
  INVALID_CONFIGURATION: "Check the public key, environment, base URLs and any conflicting Meta app ID.",
  INVALID_OPTIONS: "Check the channel ID, timeout and AbortSignal options.",
  NETWORK_ERROR: "The connection service could not be reached. Please try again.",
  HTTP_ERROR: "The connection service rejected the request.",
  INVALID_RESPONSE: "The connection service returned an invalid response.",
  POPUP_BLOCKED: "Allow popups for this application, then click Connect again.",
  TIMEOUT: "The operation timed out. Only native Meta login still awaiting its callback blocks a native retry: wait for it or reload.",
  ABORTED: "Authorization was stopped by this application. If native Meta login is still awaiting its callback, wait for it or reload before another native attempt.",
  SDK_LOAD_FAILED: "The provider SDK could not load. Check browser restrictions.",
  PROVIDER_ERROR: "The provider reported an error. Check the provider configuration before retrying.",
};

let client: OmnizapiClient | undefined;

if (typeof document !== "undefined") {
  const button = document.querySelector<HTMLButtonElement>("#connect-btn");
  const cancelButton = document.querySelector<HTMLButtonElement>("#cancel-btn");
  const statusElement = document.querySelector<HTMLElement>("#status");

  if (button && cancelButton && statusElement) {
    let controller: AbortController | undefined;
    cancelButton.addEventListener("click", () => { controller?.abort(); });

    button.addEventListener("click", async () => {
      if (button.disabled) return;
      button.disabled = true;
      statusElement.textContent = "Connecting...";

      try {
        client ??= Omnizapi.newClient({ publicKey: "your-public-key" });
        controller = new AbortController();
        cancelButton.disabled = false;
        const result = await client.connect({
          channelId: "your-channel-id",
          signal: controller.signal,
        });
        // Cancel only the SDK authorization, never imply a backend rollback.
        controller = undefined;
        cancelButton.disabled = true;

        if (!result.success) {
          statusElement.textContent = failureMessages[result.reason];
          return;
        }

        // Your backend must authorize result.channelId for the session/tenant.
        const response = await fetch("/api/connect-channel", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(result),
        });
        if (!response.ok) {
          statusElement.textContent = "The backend could not finalize the connection.";
          return;
        }

        statusElement.textContent = "Channel connected!";
      } catch (error) {
        // Do not display/log raw errors: messages may contain sensitive URLs.
        statusElement.textContent = error instanceof OmnizapiError
          ? errorMessages[error.code]
          : "Could not confirm the connection. Check its backend status before retrying.";
      } finally {
        controller = undefined;
        cancelButton.disabled = true;
        button.disabled = false;
      }
    });
  }
}
