import { EventEmitter, Subscription } from 'expo-modules-core';
import ExpoOtpRetrieverModule from './ExpoOtpRetrieverModule';

/**
 * Events emitted by the OTP Retriever module
 */
export enum OtpRetrieverEvents {
  OTP_RECEIVED = 'otpReceived',
  OTP_TIMEOUT = 'otpTimeout',
  OTP_ERROR = 'otpError',
}

/**
 * Error codes that might be returned by the module
 */
export enum OtpRetrieverErrorCodes {
  LISTENER_ERROR = 'LISTENER_ERROR',
  HASH_GENERATION_ERROR = 'HASH_GENERATION_ERROR',
  UNSUPPORTED_PLATFORM = 'UNSUPPORTED_PLATFORM',
  PLAY_SERVICES_UNAVAILABLE = 'PLAY_SERVICES_UNAVAILABLE',
}

/**
 * Error object structure returned when an error occurs
 */
export interface OtpRetrieverError {
  code: OtpRetrieverErrorCodes;
  message: string;
  details?: any;
}

// Create an event emitter to handle OTP events
const emitter = new EventEmitter(ExpoOtpRetrieverModule);

/**
 * Main class for OTP Retriever functionality
 */
class OtpRetriever {
  /**
   * Starts listening for OTP SMS messages
   * @param timeoutSeconds Optional timeout in seconds (default: 60)
   * @returns Promise that resolves when listening starts successfully
   */
  async startListener(timeoutSeconds: number = 60): Promise<void> {
    if (!ExpoOtpRetrieverModule) {
      throw this._createError(
        OtpRetrieverErrorCodes.UNSUPPORTED_PLATFORM,
        'OTP Retriever is only supported on Android'
      );
    }
    
    return await ExpoOtpRetrieverModule.startOtpListener(timeoutSeconds);
  }

  /**
   * Stops listening for OTP SMS messages
   * @returns Promise that resolves when listening stops successfully
   */
  async stopListener(): Promise<void> {
    if (!ExpoOtpRetrieverModule) {
      throw this._createError(
        OtpRetrieverErrorCodes.UNSUPPORTED_PLATFORM,
        'OTP Retriever is only supported on Android'
      );
    }
    
    return await ExpoOtpRetrieverModule.stopOtpListener();
  }

  /**
   * Generates an app signature hash needed for SMS OTP format
   * @returns Promise that resolves with the app hash string
   */
  async getAppHash(): Promise<string> {
    if (!ExpoOtpRetrieverModule) {
      throw this._createError(
        OtpRetrieverErrorCodes.UNSUPPORTED_PLATFORM,
        'OTP Retriever is only supported on Android'
      );
    }
    
    return await ExpoOtpRetrieverModule.getAppHash();
  }

  /**
   * Adds a listener for OTP events
   * @param eventName The event to listen for
   * @param listener The callback function
   * @returns Subscription object that can be used to remove the listener
   */
  addListener(
    eventName: OtpRetrieverEvents,
    listener: (event: any) => void
  ): Subscription {
    return emitter.addListener(eventName, listener);
  }

  /**
   * Helper method to create standardized error objects
   */
  private _createError(
    code: OtpRetrieverErrorCodes,
    message: string,
    details?: any
  ): OtpRetrieverError {
    return { code, message, details };
  }
}

export default new OtpRetriever();