import { EventEmitter, Subscription } from "expo-modules-core";
import { NativeModules } from "react-native";

export interface MercadoPagoConfig {
  publicKey: string;
  preferenceId?: string;
  siteId?: string;
  language?: string;
}

export interface PaymentResult {
  status: "approved" | "rejected" | "pending" | "in_process";
  paymentId: string;
  statusDetail: string;
  paymentData?: PaymentData;
  error?: {
    message: string;
    code: string;
  };
}

export interface PaymentData {
  transactionAmount: number;
  currency: string;
  description?: string;
  payer?: {
    email: string;
    name?: string;
  };
}

export interface MercadoPagoSDK {
  initialize(): Promise<void>;
  startPayment(preferenceId?: string): Promise<PaymentResult>;
  addPaymentResultListener(
    callback: (result: PaymentResult) => void,
  ): Subscription;
  removePaymentResultListener(subscription: Subscription): void;
  isMercadoPagoInstalled(): Promise<boolean>;
  getSDKVersion(): Promise<string>;
}

// Obtener el módulo nativo real
const NativeMercadoPagoModule = NativeModules.ExpoMercadoPagoModule;

class ExpoMercadoPagoModule {
  private eventEmitter = new EventEmitter(NativeMercadoPagoModule);
  private config: MercadoPagoConfig;
  private isInitialized = false;

  constructor(config: MercadoPagoConfig) {
    this.config = config;
  }

  async initialize(): Promise<void> {
    if (this.isInitialized) {
      return;
    }
    try {
      await ExpoMercadoPagoModule.initializeAsync(this.config);
      this.isInitialized = true;
    } catch (error) {
      throw new Error(`Failed to initialize MercadoPago SDK: ${error}`);
    }
  }

  async startPayment(preferenceId?: string): Promise<PaymentResult> {
    if (!this.isInitialized) {
      throw new Error(
        "MercadoPago SDK must be initialized before starting payment",
      );
    }
    const finalPreferenceId = preferenceId || this.config.preferenceId;
    if (!finalPreferenceId) {
      throw new Error(
        "Preference ID is required. Provide it in config or as parameter",
      );
    }
    try {
      return await ExpoMercadoPagoModule.startPaymentAsync(finalPreferenceId);
    } catch (error) {
      throw new Error(`Payment failed: ${error}`);
    }
  }

  addPaymentResultListener(
    callback: (result: PaymentResult) => void,
  ): Subscription {
    return this.eventEmitter.addListener("onPaymentResult", callback);
  }

  removePaymentResultListener(subscription: Subscription): void {
    this.eventEmitter.removeSubscription(subscription);
  }

  async isMercadoPagoInstalled(): Promise<boolean> {
    try {
      return await ExpoMercadoPagoModule.isMercadoPagoInstalledAsync();
    } catch (error) {
      console.warn("Error checking if MercadoPago is installed:", error);
      return false;
    }
  }

  async getSDKVersion(): Promise<string> {
    try {
      return await ExpoMercadoPagoModule.getSDKVersionAsync();
    } catch (error) {
      throw new Error(`Failed to get SDK version: ${error}`);
    }
  }

  // Métodos estáticos que llaman al módulo nativo real
  static async initializeAsync(config: MercadoPagoConfig): Promise<void> {
    return await NativeMercadoPagoModule.initializeAsync(config);
  }

  static async startPaymentAsync(preferenceId: string): Promise<PaymentResult> {
    return await NativeMercadoPagoModule.startPaymentAsync(preferenceId);
  }

  static async isMercadoPagoInstalledAsync(): Promise<boolean> {
    return await NativeMercadoPagoModule.isMercadoPagoInstalledAsync();
  }

  static async getSDKVersionAsync(): Promise<string> {
    return await NativeMercadoPagoModule.getSDKVersionAsync();
  }
}

export function createMercadoPagoSDK(
  config: MercadoPagoConfig,
): MercadoPagoSDK {
  return new ExpoMercadoPagoModule(config);
}

export default ExpoMercadoPagoModule;
