# API Reference

## Core Methods

### initialize(config)

Initialize the Freshdesk SDK with configuration. Must be called before any other methods.

```typescript
await FreshdeskSDK.initialize({
  token: string;
  host: string;
  sdkId: string;
  locale?: string;
  jwt?: string;
  debugMode?: boolean;
});
```

> **iOS:** this promise resolves only after the native SDK has had time to
> finish its own async internal loading — normally **at least ~2 seconds**,
> even on a fast network. This is expected: the native SDK gives no
> completion signal of its own, so the wrapper holds the promise instead of
> letting callers race a load that isn't done yet. See
> `PLATFORM_DIFFERENCES.md`.

### openSupport()

Open the Freshdesk support home screen.

```typescript
await FreshdeskSDK.openSupport();
```

### openKnowledgeBase()

Open the Freshdesk knowledge base / FAQ screen directly.

```typescript
await FreshdeskSDK.openKnowledgeBase();
```

### openTopic(topic)

Open a specific support topic.

```typescript
await FreshdeskSDK.openTopic({
  topicName: string;
  topicId?: string;
});
```

### getUnreadCount()

Get the current unread message count.

```typescript
const count: number = await FreshdeskSDK.getUnreadCount();
```

> **Android:** this is a cached, broadcast-driven value — it resolves `0`
> until the first broadcast arrives after `initialize()`. **iOS:** it's
> live. Prefer `addUnreadCountListener()` for a value you can trust
> immediately on both platforms. See `PLATFORM_DIFFERENCES.md`.

### dismiss()

Dismiss any open Freshdesk views.

```typescript
await FreshdeskSDK.dismiss();
```

## User Management

### resetUser()

Reset the current user and clear session data. Call this when a user logs out.

```typescript
const result = await FreshdeskSDK.resetUser();
// Returns: { success: boolean; message?: string; error?: string }
```

> **iOS:** the native SDK has no failure callback for reset — this promise
> always resolves `{ success: true }` once the SDK is initialized, even if
> the reset didn't actually succeed server-side. It only **rejects** for the
> programmer-error case (called before `initialize()` resolved). Don't rely
> on `result.success === false` as a cross-platform failure signal. See
> `PLATFORM_DIFFERENCES.md`.

### setUserProperties(properties)

Set user properties (only for non-JWT enforced SDKs).

```typescript
await FreshdeskSDK.setUserProperties({
  name: 'John Doe',
  email: 'john@example.com',
  phone: '+1234567890',
  // ... any custom properties
});
```

### setTicketProperties(properties)

Set ticket properties for creating tickets.

```typescript
await FreshdeskSDK.setTicketProperties({
  subject: 'Product Enquiry',
  priority: 3,
  // ... any custom properties
});
```

### authenticateAndUpdate(jwt)

Update or authenticate user with a new JWT token.

```typescript
await FreshdeskSDK.authenticateAndUpdate('new_jwt_token');
```

## Analytics

### trackEvent(name, properties)

Track user events for analytics and context.

```typescript
await FreshdeskSDK.trackEvent('page_view', {
  page: 'product_details',
  product_id: '12345'
});
```

> **Platform difference:** Android passes property values through with
> their original type (`string | number | boolean`). iOS coerces every
> value to a string before handing it to the native SDK — the call above
> reaches Android's analytics backend with a numeric `product_id` (if it
> were numeric) but iOS's as a string always. See
> `PLATFORM_DIFFERENCES.md`.

## SDK Information

### getSDKVersion()

Get the SDK version string.

```typescript
const version = await FreshdeskSDK.getSDKVersion();
// Returns: string (e.g., "1.0.1")
```

### getUser()

Get the current user information from the SDK.

```typescript
const user = await FreshdeskSDK.getUser();
// Returns: UserData object with user properties
```

## Diagnostics

### enableDebugLogs(enabled)

Enable or disable Freshdesk SDK debug logging. On iOS this toggles native debug logs immediately. On Android, pass `debugMode: true` to `initialize()` for Logcat output.

```typescript
await FreshdeskSDK.enableDebugLogs(true);
```

### runDiagnostics()

Run SDK diagnostics and return a structured report. Use this to verify integration and to debug configuration, network, JWT, and push issues.

On **iOS**, the report comes from the native `Freshdesk.runDiagnostics` API (FreshdeskSDK 1.3+). On **Android**, the wrapper returns integration checks (native module, init state, messaging service) plus a `runtime.diagnostics: skipped` check until native Android diagnostics parity lands.

```typescript
await FreshdeskSDK.enableDebugLogs(true);
const report = await FreshdeskSDK.runDiagnostics();

console.log(report.prettyPrinted);
console.log(report.overallStatus); // pass | warn | fail | skipped
console.log(report.platform);      // ios | android

for (const check of report.checks) {
  console.log(check.id, check.status, check.details, check.fixHint);
}
```

Each check has:

| Field | Description |
|-------|-------------|
| `id` | Check identifier (e.g. `config.token`, `push.permission`) |
| `status` | `pass`, `warn`, `fail`, or `skipped` |
| `details` | Human-readable details (secrets masked on iOS) |
| `fixHint` | Recommended fix — apply verbatim when triaging |

Helper:

```typescript
import { formatDiagnosticReport } from '@freshworks/react-native-freshdesk-sdk';

console.log(formatDiagnosticReport(report));
```

## Content Configuration

### setContentConfiguration(config)

Customize the SDK UI text, labels, and content. This allows you to override default strings for headers, placeholders, and actions.

```typescript
await FreshdeskSDK.setContentConfiguration({
  headers: {
    chat: 'Talk to our team',
    faq: 'Help Centre',
    typicallyRepliesFewMinsFallback: 'Typically replies in a few minutes',
    channelResponse: {
      offline: 'We are away right now',
      online: {
        defaultMessage: 'We typically reply in a few minutes',
        minutes: {
          one: 'Typically replies in {{time}} minute',
          more: 'Typically replies in {{time}} minutes'
        }
      }
    },
    ticketForm: {
      title: 'Raise a ticket',
      submitBtnTitle: 'Submit'
    }
  },
  placeholders: {
    replyField: 'Type your reply...',
    searchField: 'Search articles...'
  },
  privacyPolicySetting: {
    privacyPolicyMessage: 'We respect your privacy',
    privacyPolicyLinkText: 'Privacy Policy',
    privacyPolicyLink: 'https://example.com/privacy'
  },
  actions: {
    tabChat: 'Chat'
  }
});
```

> **Persistence:** Content configuration changes persist and take effect immediately. Pass an empty object `{}` to reset to widget defaults.

## Events

### addUnreadCountListener(listener)

Listen for unread message count changes.

```typescript
const subscription = FreshdeskSDK.addUnreadCountListener((event) => {
  console.log('Unread count:', event.count);
});

// Clean up
subscription?.remove();
```

### addUserStateListener(listener)

Listen for user authentication state changes.

```typescript
const subscription = FreshdeskSDK.addUserStateListener((event) => {
  console.log('User state:', event.state);
  // States: 'authenticated', 'authExpired', 'notAuthenticated', 'identifierUpdated', 'jwtNotPresent', 'undefined'
});
```

### addUserCreatedListener(listener)

Listen for new user creation events (iOS only).

```typescript
const subscription = FreshdeskSDK.addUserCreatedListener((event) => {
  console.log('New user created:', event.user);
});
```

### setLinkHandler(handler)

Set a custom link handler for URLs pressed in the SDK.

```typescript
const subscription = FreshdeskSDK.setLinkHandler((event) => {
  console.log('Link pressed:', event.url);
  // Handle the URL (e.g., with Linking.openURL)
});

// Clean up
subscription?.remove();
```

### removeAllListeners()

Remove all event listeners. Call this when cleaning up.

```typescript
FreshdeskSDK.removeAllListeners();
```

## Types

### FreshdeskConfig

```typescript
interface FreshdeskConfig {
  token: string;        // Account token
  host: string;         // Freshdesk host URL
  sdkId: string;        // SDK ID
  locale?: string;      // Locale (default: 'en')
  jwt?: string;         // JWT token for authentication
  debugMode?: boolean;  // Debug mode (Android only)
}
```

### UserState

```typescript
enum UserState {
  UNDEFINED = 'undefined',
  AUTHENTICATED = 'authenticated',
  AUTH_EXPIRED = 'authExpired',
  NOT_AUTHENTICATED = 'notAuthenticated',
  IDENTIFIER_UPDATED = 'identifierUpdated',
  JWT_ABSENT = 'jwtAbsent',
}
```

### Event Payloads

```typescript
interface UnreadCountEvent {
  count: number;
}

interface UserStateEvent {
  state: UserState;
}

interface LinkPressedEvent {
  url: string;
}

interface UserCreatedEvent {
  user: Record<string, unknown>;
}

interface ResetUserResult {
  success: boolean;
  message?: string;
  error?: string;
}

interface UserData {
  [key: string]: unknown;
}

type DiagnosticStatus = 'pass' | 'warn' | 'fail' | 'skipped';

interface DiagnosticCheck {
  id: string;
  status: DiagnosticStatus;
  details: string;
  fixHint: string;
}

interface DiagnosticReport {
  overallStatus: DiagnosticStatus | string;
  checks: DiagnosticCheck[];
  prettyPrinted: string;
  platform: 'ios' | 'android';
}

interface ContentConfiguration {
  headers?: HeaderContent;
  placeholders?: PlaceholderContent;
  privacyPolicySetting?: PrivacyPolicyContent;
  actions?: ActionContent;
  additionalFields?: Record<string, unknown>;
}

interface HeaderContent {
  chat?: string;
  faq?: string;
  faqMessageUs?: string;
  faqNotAvailable?: string;
  faqSearchNotAvailable?: string;
  faqThankyou?: string;
  faqUseful?: string;
  faqNotUseful?: string;
  channelResponse?: ChannelResponseContent;
  ticketForm?: TicketFormContent;
  typicallyRepliesFewMinsFallback?: string;
}

interface ChannelResponseContent {
  offline?: string;
  online?: ChannelResponseOnline;
}

interface ChannelResponseOnline {
  defaultMessage?: string;
  minutes?: ChannelResponseTimeUnit;
  hours?: ChannelResponseTimeUnit;
}

interface ChannelResponseTimeUnit {
  one?: string;
  more?: string;
}

interface TicketFormContent {
  title?: string;
  submitBtnTitle?: string;
}

interface PlaceholderContent {
  replyField?: string;
  searchField?: string;
}

interface PrivacyPolicyContent {
  privacyPolicyMessage?: string;
  privacyPolicyLinkText?: string;
  privacyPolicyLink?: string;
}

interface ActionContent {
  tabChat?: string;
}
```

## Event Constants

```typescript
import { FreshdeskEvents } from '@freshworks/react-native-freshdesk-sdk';

FreshdeskEvents.UNREAD_COUNT_CHANGED;  // 'unreadCountChanged'
FreshdeskEvents.USER_STATE_CHANGED;    // 'userStateChanged'
FreshdeskEvents.USER_CREATED;          // 'userCreated'
FreshdeskEvents.ON_LINK_PRESSED;       // 'onLinkPressed'
```

## Complete Example

```typescript
import React, { useEffect } from 'react';
import FreshdeskSDK, { FreshdeskEvents } from '@freshworks/react-native-freshdesk-sdk';

function App() {
  useEffect(() => {
    // Initialize SDK
    FreshdeskSDK.initialize({
      token: 'your_token',
      host: 'your_host.freshdesk.com',
      sdkId: 'your_sdk_id',
    });

    // Set up event listeners
    const unreadSub = FreshdeskSDK.addUnreadCountListener((event) => {
      console.log('Unread:', event.count);
    });

    const userStateSub = FreshdeskSDK.addUserStateListener((event) => {
      if (event.state === 'authExpired') {
        // Refresh JWT and re-authenticate
      }
    });

    // Clean up
    return () => {
      unreadSub?.remove();
      userStateSub?.remove();
      FreshdeskSDK.removeAllListeners();
    };
  }, []);

  const handleSupport = async () => {
    try {
      await FreshdeskSDK.openSupport();
    } catch (error) {
      console.error('Failed to open support:', error);
    }
  };

  return (
    <Button title="Contact Support" onPress={handleSupport} />
  );
}
```
