# Platform behavior differences

`FreshdeskSDK`'s public API is the same on both platforms, but a few methods have
different **runtime behavior** because the underlying native Android and iOS SDKs
don't expose the same capability. These are not bugs in this wrapper — the
divergence is inherent to what each native SDK can report — but they're
documented here because the JS types can't express them.

## `resetUser()`

- **Android:** the native SDK has both `onSuccess` and `onFailure` callbacks, so
  a genuine failure (e.g. a network error during reset) resolves
  `{ success: false, error }`.
- **iOS:** the native SDK's `resetUser()` call is synchronous and has **no
  failure callback at all**. This wrapper cannot detect a reset failure on iOS —
  it always resolves `{ success: true }` once the SDK is initialized. The
  promise only **rejects** for the programmer-error case (`resetUser()` called
  before `initialize()` resolved).

**Do not rely on `resetUser()` resolving `{ success: false }` as a cross-platform
signal.** Treat a resolved promise as "reset was requested"; a rejected promise
as a usage error. If you need confirmed reset-failure detection on iOS, that
requires a completion handler on the native `Freshdesk.resetUser()` API, which
is a native-SDK feature request, not something this wrapper can add.

## `initialize(config)` settle delay (iOS)

- **iOS:** the native SDK's `Freshdesk.initialize(with:)` has no completion
  callback, `async` variant, notification, or published readiness property —
  confirmed by inspecting both the public and private `.swiftinterface` files
  in the vendored `FreshdeskSDK.xcframework`. It does its own async internal
  loading after `initialize()` returns, and calls made before that finishes
  are silently queued/dropped by the native SDK itself (logged as "Tasks will
  be executed once the SDK is loaded"). This wrapper cannot detect real
  readiness, so `initialize()`'s promise resolves only after a fixed
  **2-second settle delay** past the native call returning, not the instant it
  returns. This is a heuristic, not a guarantee — there is no telemetry on the
  native SDK's real load time behind that number.
- **Android:** `initialize()` waits on the native SDK's real init callback (or
  a readiness re-check / hard timeout as a fallback — see
  `FreshdeskInitCoordinator`), so it resolves only once the SDK has actually
  confirmed readiness, with no fixed heuristic delay involved.

**Practical effect:** `initialize()` on iOS always takes at least ~2 seconds,
even on a fast/local network, where Android can resolve sooner if the native
callback fires quickly. If you called `openSupport()` / `trackEvent()` /
`setUserProperties()` / `setTicketProperties()` immediately after
`initialize()` resolved and saw them silently fail intermittently (or nearly
always) on iOS before this delay was added, that was this exact race —
not a bug in your integration code.

## `trackEvent(name, properties)`

- **Android:** property values reach the native SDK with their original type
  (`string | number | boolean`) — the wrapper passes the properties object
  straight through as a typed map.
- **iOS:** every property value is coerced to a string (`String(describing:)`)
  before being handed to the native SDK, because `Freshdesk.trackUserEvents`
  takes a `[String: String]` payload. `trackEvent('purchase', { amount: 42 })`
  reaches Android's analytics backend with a numeric `amount`, but iOS's with
  the string `"42"`.

**If your analytics backend distinguishes types (e.g. numeric aggregation on
`amount`), be aware iOS always reports strings.** This is a native-SDK
constraint (`Freshdesk.trackUserEvents`'s payload type), not something this
wrapper can normalize without silently lying about the Android value's type.

## `enableDebugLogs(enabled)`

- **iOS:** toggles debug logging at runtime.
- **Android:** the native SDK only accepts a debug-logging flag at
  `SDKConfig` construction time (`initialize()`). Calling
  `enableDebugLogs(true)` **after** `initialize()` is a no-op on Android unless
  you already passed `debugMode: true` to `initialize()` — it does not
  retroactively enable logging, and does not re-initialize the SDK to do so.
  Calling `enableDebugLogs(true)` before `initialize()` resolves rejects with
  `FreshdeskErrorCode.NOT_INITIALIZED`.

**To get Android debug logs, pass `debugMode: true` to `initialize()`.**
`enableDebugLogs()` is reliable only on iOS; treat it as an iOS-only runtime
toggle and use `initialize({ debugMode })` for Android.

## `getUnreadCount()`

- **Android:** the native SDK does not expose a synchronous "current count"
  getter — it only pushes count changes via a broadcast. This wrapper caches
  the last broadcast value and returns it, so it resolves `0` until the first
  broadcast arrives after `initialize()` (there is no reliable way to fetch the
  count eagerly).
- **iOS:** the native SDK exposes the count directly, so this call resolves the
  live value.

For a value you can trust immediately after `initialize()` on both platforms,
prefer `addUnreadCountListener()` over polling `getUnreadCount()`.

## Error codes

Not every `FreshdeskErrorCode` is rejected on both platforms — Android has
several method-specific codes (`TRACK_ERROR`, `TICKET_PROPERTIES_ERROR`,
`AUTH_ERROR`, `DISMISS_ERROR`, `OPEN_ERROR`, `NO_ACTIVITY`, `INIT_TIMEOUT`,
`INIT_ERROR`, `NOT_READY`) that iOS does not emit, and iOS has two of its own
(`NO_VIEW_CONTROLLER`, `USER_PARSE_ERROR`). See the JSDoc on each
`FreshdeskErrorCode` member for which platform(s) it can occur on.
