import { h } from "@stencil/core";
import { StyledHost } from "../../ui-components";
import { checkPkgVersion } from "../../utils/check-pkg-version";
import JustifiAnalytics from "../../api/Analytics";
import { ComponentErrorCodes, ComponentErrorSeverity, } from "../../api";
import { checkoutStore } from "../../store/checkout.store";
import { PAYMENT_METHODS } from "../modular-checkout/ModularCheckout";
// Constants
const PAYMENT_METHOD_TYPE_LABELS = {
    [PAYMENT_METHODS.NEW_BANK_ACCOUNT]: 'New bank account',
    [PAYMENT_METHODS.NEW_CARD]: 'New credit or debit card',
};
const ERROR_MESSAGES = {
    AUTH_TOKEN_REQUIRED: 'Auth token is required when using the tokenize-payment-method component not slotted in justifi-modular-checkout',
    ACCOUNT_ID_REQUIRED: 'Account ID is required when using the tokenize-payment-method component not slotted in justifi-modular-checkout',
    FORM_NOT_READY: 'Payment form not ready',
    VALIDATION_ERROR: 'Validation error',
};
export class JustifiTokenizePaymentMethod {
    constructor() {
        this.computedHideSubmitButton = false;
        this.isLoading = false;
        this.submitButtonText = 'Submit';
    }
    paymentMethodsChanged() {
        this.setDefaultSelectedPaymentMethod();
    }
    connectedCallback() {
        this.setDefaultSelectedPaymentMethod();
        this.setComputedHideSubmitButton();
    }
    disconnectedCallback() {
        var _a;
        (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.cleanup();
        if (this.unsubscribeFromStore) {
            this.unsubscribeFromStore();
        }
    }
    componentWillLoad() {
        checkPkgVersion();
        this.analytics = new JustifiAnalytics(this);
    }
    handleRadioClick(event) {
        this.selectedPaymentMethod = event.detail;
        checkoutStore.selectedPaymentMethod = { type: event.detail };
    }
    async tokenizePaymentMethod(event) {
        event === null || event === void 0 ? void 0 : event.preventDefault();
        this.validateRequiredProps();
        this.isLoading = true;
        try {
            const validation = await this.validate();
            if (!validation.isValid) {
                this.errorEvent.emit({
                    errorCode: ComponentErrorCodes.TOKENIZE_ERROR,
                    message: ERROR_MESSAGES.VALIDATION_ERROR,
                });
                this.isLoading = false;
                return;
            }
            const tokenizeResponse = await this.resolvePaymentMethod({ isValid: true });
            if (tokenizeResponse.error) {
                this.emitError({
                    errorCode: tokenizeResponse.error.code,
                    message: tokenizeResponse.error.message,
                });
            }
            this.submitEvent.emit({ response: tokenizeResponse });
            return tokenizeResponse;
        }
        catch (error) {
            const errorResponse = this.createErrorResponse(ComponentErrorCodes.TOKENIZE_ERROR, error.message);
            this.emitError({
                errorCode: ComponentErrorCodes.TOKENIZE_ERROR,
                message: error.message,
            });
            this.submitEvent.emit({ response: errorResponse });
            return errorResponse;
        }
        finally {
            this.isLoading = false;
        }
    }
    async fillBillingForm(fields) {
        checkoutStore.billingFormFields = fields;
    }
    async validate() {
        if (!this.areFormsReady()) {
            return { isValid: false, errors: { general: ERROR_MESSAGES.FORM_NOT_READY } };
        }
        const [billingValidation, paymentMethodValidation] = await Promise.all([
            this.billingFormRef.validate(),
            this.paymentMethodFormRef.validate(),
        ]);
        const result = {
            isValid: billingValidation.isValid && paymentMethodValidation.isValid,
            errors: Object.assign(Object.assign({}, billingValidation.errors), paymentMethodValidation.errors),
        };
        return result;
    }
    async getValues() {
        return this.billingFormRef.getValues();
    }
    async tokenize() {
        try {
            const billingFormFieldValues = await this.billingFormRef.getValues();
            const config = {
                clientId: this.authToken || checkoutStore.authToken,
                account: this.accountId || checkoutStore.accountId,
                paymentMethodMetadata: this.buildPaymentMethodMetadata(billingFormFieldValues),
            };
            const result = await this.paymentMethodFormRef.tokenize(config);
            return result;
        }
        catch (error) {
            return error;
        }
    }
    // 9. Local methods
    validateRequiredProps() {
        if (!this.authToken && !checkoutStore.authToken) {
            this.emitError({
                errorCode: ComponentErrorCodes.TOKENIZE_ERROR,
                message: ERROR_MESSAGES.AUTH_TOKEN_REQUIRED,
            });
        }
        if (!this.accountId && !checkoutStore.accountId) {
            this.emitError({
                errorCode: ComponentErrorCodes.TOKENIZE_ERROR,
                message: ERROR_MESSAGES.ACCOUNT_ID_REQUIRED,
            });
        }
    }
    setDefaultSelectedPaymentMethod() {
        if (this.selectedPaymentMethod) {
            return;
        }
        if (!this.disableCreditCard) {
            this.selectedPaymentMethod = PAYMENT_METHODS.NEW_CARD;
            checkoutStore.selectedPaymentMethod = { type: PAYMENT_METHODS.NEW_CARD };
        }
        else if (!this.disableBankAccount &&
            (!checkoutStore.checkoutLoaded || checkoutStore.achPaymentsEnabled)) {
            this.selectedPaymentMethod = PAYMENT_METHODS.NEW_BANK_ACCOUNT;
            checkoutStore.selectedPaymentMethod = { type: PAYMENT_METHODS.NEW_BANK_ACCOUNT };
        }
    }
    setComputedHideSubmitButton() {
        // If hideSubmitButton prop is explicitly set, use that value
        if (this.hideSubmitButton !== undefined) {
            this.computedHideSubmitButton = this.hideSubmitButton;
            return;
        }
        // Otherwise, auto-detect if component is slotted within modular-checkout
        const isWithinModularCheckout = this.isSlottedWithinModularCheckout();
        this.computedHideSubmitButton = isWithinModularCheckout;
    }
    isSlottedWithinModularCheckout() {
        var _a;
        let parent = (_a = this.host) === null || _a === void 0 ? void 0 : _a.parentElement;
        while (parent) {
            if (parent.tagName === 'JUSTIFI-MODULAR-CHECKOUT') {
                return true;
            }
            parent = parent.parentElement;
        }
        return false;
    }
    get availablePaymentMethods() {
        const methods = [];
        const achAllowedForCheckout = !checkoutStore.checkoutLoaded || checkoutStore.achPaymentsEnabled;
        if (!this.disableCreditCard) {
            methods.push(PAYMENT_METHODS.NEW_CARD);
        }
        if (!this.disableBankAccount && achAllowedForCheckout) {
            methods.push(PAYMENT_METHODS.NEW_BANK_ACCOUNT);
        }
        return methods;
    }
    areFormsReady() {
        return !!(this.billingFormRef && this.paymentMethodFormRef);
    }
    emitError(errorData) {
        this.errorEvent.emit(Object.assign(Object.assign({}, errorData), { severity: ComponentErrorSeverity.ERROR }));
    }
    createErrorResponse(code, message) {
        return {
            error: {
                code: code,
                message,
                decline_code: undefined,
            },
        };
    }
    async resolvePaymentMethod(insuranceValidation) {
        if (!this.areFormsReady()) {
            return this.createErrorResponse('form_not_ready', ERROR_MESSAGES.FORM_NOT_READY);
        }
        try {
            const validation = await this.validate();
            if (!validation.isValid || !insuranceValidation.isValid) {
                const errorMessage = Object.values(validation.errors)[0] || ERROR_MESSAGES.VALIDATION_ERROR;
                return {
                    validationError: true,
                    error: {
                        code: 'validation_error',
                        message: String(errorMessage),
                        decline_code: undefined,
                    },
                };
            }
            const result = await this.performTokenization();
            return result;
        }
        catch (error) {
            return { error };
        }
    }
    async performTokenization() {
        var _a, _b;
        const tokenizeResponse = await this.tokenize();
        if (tokenizeResponse.error) {
            return { error: tokenizeResponse.error };
        }
        const tokenizeResponseData = tokenizeResponse.data;
        const result = {
            token: ((_a = tokenizeResponseData.card) === null || _a === void 0 ? void 0 : _a.token) || ((_b = tokenizeResponseData.bank_account) === null || _b === void 0 ? void 0 : _b.token),
            data: tokenizeResponseData,
        };
        return result;
    }
    buildPaymentMethodMetadata(billingFormFieldValues) {
        return this.shouldSavePaymentMethod
            ? Object.assign(Object.assign({}, billingFormFieldValues), { payment_method_group_id: this.paymentMethodGroupID }) : Object.assign({}, billingFormFieldValues);
    }
    get paymentMethodGroupID() {
        return this.paymentMethodGroupId || checkoutStore.paymentMethodGroupId;
    }
    get shouldSavePaymentMethod() {
        return !!(this.paymentMethodGroupId || checkoutStore.savePaymentMethod);
    }
    get shouldHideRadioInput() {
        return this.disableCreditCard || this.disableBankAccount;
    }
    renderPaymentMethodOption(paymentMethodType) {
        const isSelected = this.selectedPaymentMethod === paymentMethodType && checkoutStore.selectedPaymentMethod.id === undefined;
        return (h("div", { class: "payment-method" }, h("radio-list-item", { name: "paymentMethodType", value: paymentMethodType, checked: isSelected, label: PAYMENT_METHOD_TYPE_LABELS[paymentMethodType], hidden: this.shouldHideRadioInput }), isSelected && this.renderSelectedPaymentMethodForm(paymentMethodType)));
    }
    renderSelectedPaymentMethodForm(paymentMethodType) {
        return (h("div", { class: "mt-4 pb-4" }, this.renderPaymentMethodForm(paymentMethodType), h("div", { class: "mt-4" }, h("billing-form", { ref: (el) => {
                if (el)
                    this.billingFormRef = el;
            }, hideCardBillingForm: this.hideCardBillingForm, hideBankAccountBillingForm: this.hideBankAccountBillingForm, paymentMethodType: paymentMethodType })), h("div", { class: "mt-4" }, h("save-new-payment-method", { hidden: !this.paymentMethodGroupID, label: this.savePaymentMethodLabel }))));
    }
    renderPaymentMethodForm(paymentMethodType) {
        return paymentMethodType === PAYMENT_METHODS.NEW_CARD ? (h("card-form", { ref: (el) => {
                if (el)
                    this.paymentMethodFormRef = el;
            } })) : (h("bank-account-form", { ref: (el) => {
                if (el)
                    this.paymentMethodFormRef = el;
            } }));
    }
    render() {
        return (h(StyledHost, { key: 'bc76697688be332ef84db56e61b6b455a6d1e986' }, h("form", { key: '8f64f55f945d4ff4ed0f144c724dbd71278ec771' }, h("fieldset", { key: '15b6d388117738391089cf91f999247cddb29714' }, h("div", { key: 'a4e23f7808b446dff6f7da437dba3cb57d2d62aa', class: "row gy-3" }, h("div", { key: '63b0584d217d9bb50036eb7d5837e7287be58760', class: "col-12" }, this.availablePaymentMethods.map((method) => this.renderPaymentMethodOption(method))), h("div", { key: 'c9345be3429cd8ab01a84e8584270938feceba39', class: "col-12" }, h("internal-button", { key: 'aa56df7b6b1250e9b81fbc281b969d2a37a05428', text: this.submitButtonText, variant: "primary", type: "submit", clickHandler: (e) => this.tokenizePaymentMethod(e), isLoading: this.isLoading, "data-testid": "submit-button", hidden: this.computedHideSubmitButton })))))));
    }
    static get is() { return "justifi-tokenize-payment-method"; }
    static get encapsulation() { return "shadow"; }
    static get properties() {
        return {
            "accountId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "account-id"
            },
            "authToken": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "auth-token"
            },
            "disableBankAccount": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disable-bank-account"
            },
            "disableCreditCard": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disable-credit-card"
            },
            "hideBankAccountBillingForm": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hide-bank-account-billing-form"
            },
            "hideCardBillingForm": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hide-card-billing-form"
            },
            "hideSubmitButton": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hide-submit-button"
            },
            "paymentMethodGroupId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "payment-method-group-id"
            },
            "submitButtonText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "submit-button-text",
                "defaultValue": "'Submit'"
            },
            "savePaymentMethodLabel": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "save-payment-method-label"
            }
        };
    }
    static get states() {
        return {
            "computedHideSubmitButton": {},
            "isLoading": {},
            "selectedPaymentMethod": {}
        };
    }
    static get events() {
        return [{
                "method": "errorEvent",
                "name": "error-event",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "ComponentErrorEvent",
                    "resolved": "ComponentErrorEvent",
                    "references": {
                        "ComponentErrorEvent": {
                            "location": "import",
                            "path": "../../api",
                            "id": "src/api/index.ts::ComponentErrorEvent"
                        }
                    }
                }
            }, {
                "method": "submitEvent",
                "name": "submit-event",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "ComponentSubmitEvent",
                    "resolved": "ComponentSubmitEvent",
                    "references": {
                        "ComponentSubmitEvent": {
                            "location": "import",
                            "path": "../../api",
                            "id": "src/api/index.ts::ComponentSubmitEvent"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "tokenizePaymentMethod": {
                "complexType": {
                    "signature": "(event?: MouseEvent) => Promise<PaymentMethodPayload>",
                    "parameters": [{
                            "name": "event",
                            "type": "MouseEvent",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "PaymentMethodPayload": {
                            "location": "import",
                            "path": "../checkout/payment-method-payload",
                            "id": "src/components/checkout/payment-method-payload.ts::PaymentMethodPayload"
                        },
                        "MouseEvent": {
                            "location": "global",
                            "id": "global::MouseEvent"
                        },
                        "ComponentErrorCodes": {
                            "location": "import",
                            "path": "../../api",
                            "id": "src/api/index.ts::ComponentErrorCodes"
                        }
                    },
                    "return": "Promise<PaymentMethodPayload>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            },
            "fillBillingForm": {
                "complexType": {
                    "signature": "(fields: BillingFormFields) => Promise<void>",
                    "parameters": [{
                            "name": "fields",
                            "type": "BillingFormFields",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "BillingFormFields": {
                            "location": "import",
                            "path": "../checkout/billing-form/billing-form-schema",
                            "id": "src/components/checkout/billing-form/billing-form-schema.ts::BillingFormFields"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            },
            "validate": {
                "complexType": {
                    "signature": "() => Promise<ValidationResult>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "ValidationResult": {
                            "location": "global",
                            "id": "global::ValidationResult"
                        }
                    },
                    "return": "Promise<ValidationResult>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            },
            "getValues": {
                "complexType": {
                    "signature": "() => Promise<BillingFormFields>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "BillingFormFields": {
                            "location": "import",
                            "path": "../checkout/billing-form/billing-form-schema",
                            "id": "src/components/checkout/billing-form/billing-form-schema.ts::BillingFormFields"
                        }
                    },
                    "return": "Promise<BillingFormFields>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            },
            "tokenize": {
                "complexType": {
                    "signature": "() => Promise<any>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "TokenizeConfig": {
                            "location": "global",
                            "id": "global::TokenizeConfig"
                        }
                    },
                    "return": "Promise<any>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "disableCreditCard",
                "methodName": "paymentMethodsChanged"
            }, {
                "propName": "disableBankAccount",
                "methodName": "paymentMethodsChanged"
            }];
    }
    static get listeners() {
        return [{
                "name": "radio-click",
                "method": "handleRadioClick",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
