import { init,InitResult,createElement, type Payment } from '@airwallex/components-sdk';

// export {Payment};
export type AirwallexCartNumberElementType = Payment.CardNumberElementType;
export type AirwallexCvcElementType = Payment.CvcElementType;
export type AirwallexExpiryDateElementType = Payment.ExpiryDateElementType;

export interface AirwallexCardElements{
  cardNumber?: AirwallexCartNumberElementType;
  cvc?: AirwallexCvcElementType;
  expiry?: AirwallexExpiryDateElementType;
}

type ElementType =
  | AirwallexCartNumberElementType
  | AirwallexCvcElementType
  | AirwallexExpiryDateElementType;

let initPromise: Promise<InitResult> | null = null;


export function airwallexInit() {


  if (!initPromise) {

    initPromise = init({
      env:
        process.env.NEXT_PUBLIC_APP_ENV !== 'production'
          ? 'demo'
          : 'prod',

      enabledElements: ['payments'],
    });

  }


  return initPromise;
}


class AirwallexManager {
  private elements: AirwallexCardElements = {};
  private createPromise: Promise<AirwallexCardElements> | null = null;

  private listeners = new Map<ElementType, Map<Payment.SplitElementEventCode, boolean>>();

  // private created = false;

  // async init() {
  //   if (this.created) return;
  //   this.created = true;
  // }

  async createElements() {

    if (this.elements.cardNumber) {

      return this.elements;
    }

    if (this.createPromise) {

      return this.createPromise;
    }



    
    this.createPromise = Promise.all([
      createElement("cardNumber"),
      createElement("cvc"),
      createElement("expiry")
    ]).then(([cardNumber,cvc,expiry]) => {

      this.elements = {
        cardNumber,
        cvc,
        expiry
      };

      return this.elements;

    });


    return this.createPromise;


  }

  mount(containerIds: {
    cardNumber: string;
    cvc: string;
    expiry: string;
  }) {
    this.elements.cardNumber?.mount(containerIds.cardNumber);
    this.elements.cvc?.mount(containerIds.cvc);
    this.elements.expiry?.mount(containerIds.expiry);
  }

  unmount() {
    this.elements.cardNumber?.unmount();
    this.elements.cvc?.unmount();
    this.elements.expiry?.unmount();
  }

  on<EventCode extends Payment.SplitElementEventCode>(el: ElementType, event: EventCode, handler: Payment.SplitElementEventHandler<EventCode>) {
    let eventMap = this.listeners.get(el);
    
    if (!eventMap) {
      eventMap = new Map<Payment.SplitElementEventCode, boolean>([[event, false]]);
      this.listeners.set(el, eventMap);
    }
    if(eventMap.get(event)) return; // 注册过就返回

    el.on(event, handler);

    eventMap.set(event,true);
    
  }



  destroy() {
    const { cardNumber, cvc, expiry } = this.elements;

    [cardNumber, cvc, expiry].forEach((el) => {
      if (!el) return;
      el.unmount();
      el.destroy();
    });

    this.elements = {};
  }

  getElements() {
    return this.elements;
  }
}

export const airwallexManager = new AirwallexManager();