import { NativeModules, Platform } from 'react-native';

const LINKING_ERROR =
  `The package 'feedback-react-native-sdk' doesn't seem to be linked. Make sure: \n\n` +
  Platform.select({
    ios: "- You have run 'pod install'\n",
    android: '- You have rebuilt the Android app\n',
    default: '',
  }) +
  '- You rebuilt the app after installing the package';

const g = global as Record<string, unknown>;
const isTurboModuleEnabled =
  g.__turboModuleProxy != null || g.RN$Bridgeless != null;

const FeedbackReactNativeSdkModule = isTurboModuleEnabled
  ? require('./NativeFeedbackReactNativeSdk').default
  : NativeModules.FeedbackReactNativeSdk;

const FeedbackReactNativeSdk = FeedbackReactNativeSdkModule
  ? FeedbackReactNativeSdkModule
  : new Proxy(
      {},
      {
        get() {
          throw new Error(LINKING_ERROR);
        },
      }
    );

export enum feedbackSDKViewMode {
  Default = 0,
  BottomSheet = 1,
}

export enum feedbackSDKCallback {
  None = 0,
  Closed,
  SendFeedback,
  Outside,
  Opened,
  DisplayOnce,
  PreventMultipleFeedback,
  QuotaExceeded,
  DisplayRateLimited,
  SurveyPassive,
  HealthCheckFailed,
}

export function feedbackSDKDebugMode(debugMode: boolean): void {
  FeedbackReactNativeSdk.debugMode(debugMode);
}

const mapToObject = (
  value: Map<string, any> | null | undefined
): Record<string, any> | null => {
  if (!value) return null;
  try {
    return Object.fromEntries(value.entries());
  } catch {
    return null;
  }
};

const CUSTOMER_KEY_MAP: Record<string, string> = {
  phone_number: 'phoneNumber',
  external_id: 'externalId',
  custom_attrs: 'customAttributes',
  custom_attributes: 'customAttributes',
};

const normalizeCustomerKeys = (
  obj: Record<string, any> | null
): Record<string, any> | null => {
  if (!obj) return null;
  const result: Record<string, any> = {};
  for (const [key, value] of Object.entries(obj)) {
    result[CUSTOMER_KEY_MAP[key] ?? key] = value;
  }
  return result;
};

export function feedbackSDKBoot(
  appId: string,
  accessKey: string,
  code: string,
  apiUrl: string,
  feedbackUrl: string,
  eventUrl?: string,
  callback?: (status: string) => void
): void {
  const eventUrlValue = isTurboModuleEnabled ? eventUrl ?? '' : eventUrl;
  FeedbackReactNativeSdk.boot(
    appId,
    accessKey,
    code,
    apiUrl,
    feedbackUrl,
    eventUrlValue,
    (status: string) => {
      if (callback != null) {
        callback(status);
      }
    }
  );
}

export function feedbackSDKShow(
  viewMode: feedbackSDKViewMode,
  title: string | null,
  titleFontSize: number | null,
  code: string | null | undefined,
  language: string | null,
  customer: Map<string, any> | null,
  payload: Map<string, string> | null,
  callback: (status: feedbackSDKCallback | undefined | string) => void
): void {
  const viewModeValue: number = viewMode;
  const titleFontSizeValue = isTurboModuleEnabled
    ? titleFontSize ?? 0
    : titleFontSize?.toString();
  const codeValue = code != null && code !== '' ? code : null;
  const customerObj = normalizeCustomerKeys(mapToObject(customer));
  const payloadObj = mapToObject(payload);
  const customerValue = customerObj ?? (isTurboModuleEnabled ? {} : null);
  const payloadValue = payloadObj ?? (isTurboModuleEnabled ? {} : null);

  FeedbackReactNativeSdk.show(
    viewModeValue,
    title,
    titleFontSizeValue,
    codeValue,
    language,
    customerValue,
    payloadValue,
    (status: number) => {
      if (callback != null) {
        callback(Object.values(feedbackSDKCallback)[status]);
      }
    }
  );
}

export function feedbackSDKClear(): void {
  FeedbackReactNativeSdk.clear();
}
