import ExpoModulesCore
import MercadoPagoSDK

public class ExpoMercadoPagoModule: Module {
  private var publicKey: String?
  private var siteId: String = "MLA"
  private var language: String = "es"
  private var currentPromise: Promise?
  
  public func definition() -> ModuleDefinition {
    Name("ExpoMercadoPagoModule")
    
    AsyncFunction("initializeAsync") { (config: [String: Any]) in
      guard let publicKey = config["publicKey"] as? String, !publicKey.isEmpty else {
        throw MercadoPagoError.invalidConfig("Public key is required")
      }
      
      self.publicKey = publicKey
      self.siteId = config["siteId"] as? String ?? "MLA"
      self.language = config["language"] as? String ?? "es"
    }
    
    AsyncFunction("startPaymentAsync") { (preferenceId: String) in
      guard let publicKey = self.publicKey else {
        throw MercadoPagoError.notInitialized("Module not initialized. Call initializeAsync first.")
      }
      
      guard let currentViewController = self.appContext?.utilities?.currentViewController() else {
        throw MercadoPagoError.noViewController("No view controller available")
      }
      
      self.currentPromise = Promise()
      
      let builder = MercadoPagoCheckout.Builder(publicKey: publicKey, preferenceId: preferenceId)
      let checkout = builder.build()
      
      checkout.start(navigationController: currentViewController.navigationController ?? UINavigationController(rootViewController: currentViewController), lifeCycleProtocol: self)
      
      return self.currentPromise?.await()
    }
    
    AsyncFunction("isMercadoPagoInstalledAsync") { () -> Bool in
      return MercadoPagoCheckout.isMercadoPagoInstalled()
    }
    
    AsyncFunction("getSDKVersionAsync") { () -> String in
      return MercadoPagoCheckout.getVersion()
    }
  }
}

extension ExpoMercadoPagoModule: PXLifeCycleProtocol {
  public func finishCheckout() -> (UIViewController, PXAction?) {
    // This method is required by the protocol but not used in our implementation
    return (UIViewController(), nil)
  }
  
  public func cancelCheckout() -> (UIViewController, PXAction?) {
    // This method is required by the protocol but not used in our implementation
    return (UIViewController(), nil)
  }
  
  public func changePaymentMethodTapped() -> (UIViewController, PXAction?) {
    // This method is required by the protocol but not used in our implementation
    return (UIViewController(), nil)
  }
}

extension ExpoMercadoPagoModule: PXResultHandler {
  public func handlePayment(payment: PXResult) {
    let result: [String: Any]
    
    switch payment {
    case let payment as PXGenericPayment:
      result = [
        "status": payment.status,
        "paymentId": payment.paymentId,
        "statusDetail": payment.statusDetail,
        "paymentData": [
          "transactionAmount": payment.transactionAmount,
          "currency": payment.currencyId,
          "description": payment.paymentDescription ?? ""
        ]
      ]
    case let payment as PXBusinessResult:
      result = [
        "status": payment.status,
        "paymentId": payment.paymentId,
        "statusDetail": payment.statusDetail,
        "paymentData": [
          "transactionAmount": payment.transactionAmount,
          "currency": payment.currencyId,
          "description": payment.paymentDescription ?? ""
        ]
      ]
    default:
      result = [
        "status": "unknown",
        "paymentId": "",
        "statusDetail": "Unknown payment result",
        "error": [
          "message": "Unknown payment result type",
          "code": "UNKNOWN"
        ]
      ]
    }
    
    self.sendEvent("onPaymentResult", result)
    self.currentPromise?.resolve(result)
    self.currentPromise = nil
  }
  
  public func handleError(error: PXError) {
    let result: [String: Any] = [
      "status": "rejected",
      "paymentId": "",
      "statusDetail": error.message,
      "error": [
        "message": error.message,
        "code": error.errorCode
      ]
    ]
    
    self.sendEvent("onPaymentResult", result)
    self.currentPromise?.reject(MercadoPagoError.paymentFailed(error.message))
    self.currentPromise = nil
  }
}

enum MercadoPagoError: Error {
  case invalidConfig(String)
  case notInitialized(String)
  case noViewController(String)
  case paymentFailed(String)
  
  var localizedDescription: String {
    switch self {
    case .invalidConfig(let message):
      return "Invalid configuration: \(message)"
    case .notInitialized(let message):
      return "Not initialized: \(message)"
    case .noViewController(let message):
      return "No view controller: \(message)"
    case .paymentFailed(let message):
      return "Payment failed: \(message)"
    }
  }
} 