import { h, proxyCustomElement, HTMLElement, createEvent } from '@stencil/core/internal/client';
import { c as create$3, a as create$6, F as FormController } from './form.js';
import { b as formatCurrency } from './utils2.js';
import './config-state.js';
import { R as RefundReasons, C as ComponentErrorSeverity, a as ComponentErrorCodes, u as RefundPayload } from './Plaid.js';
import './Pagination.js';
import './Business.js';
import './ApplePay.js';
import { B as Button } from './button.js';
import { S as StyledHost } from './styled-host.js';
import './justifi-details2.js';
import './event-types.js';
import './justifi-radio-list-item2.js';
import { P as PaymentService } from './payment.service.js';
import { m as makeGetPaymentDetails } from './get-payment-details.js';
import { J as JustifiAnalytics } from './Analytics.js';
import { c as checkPkgVersion } from './check-pkg-version.js';
import { g as getErrorCode, a as getErrorMessage } from './utils3.js';
import { A as Api } from './Api.js';
import { S as Skeleton } from './skeleton.js';
import { d as defineCustomElement$7 } from './custom-popper2.js';
import { d as defineCustomElement$6 } from './form-control-help-text3.js';
import { d as defineCustomElement$5 } from './form-control-monetary2.js';
import { d as defineCustomElement$4 } from './form-control-select2.js';
import { d as defineCustomElement$3 } from './form-control-textarea2.js';
import { d as defineCustomElement$2 } from './form-control-tooltip2.js';

const amountValidation = (maxAmount) => {
    const max = +maxAmount;
    return (create$6()
        .required('Amount is required')
        .test('max-amount', `Refund amount cannot be more than payment amount: ${formatCurrency(max)}`, function (value) {
        return +value <= +max;
    })
        .test('min-amount', 'Refund amount must be greater than 0', function (value) {
        return +value > 0;
    }));
};
const RefundPaymentSchema = (maxRefundAmount) => {
    if (!maxRefundAmount) {
        return;
    }
    const schema = create$3({
        amount: amountValidation(maxRefundAmount),
        description: create$6().optional(),
        reason: create$6().optional()
            .oneOf([
            RefundReasons.customerRequest,
            RefundReasons.duplicate,
            RefundReasons.fraudulent,
        ], 'Select a reason')
    });
    return schema;
};

const refundReasonOptions = [
    {
        label: 'Select a reason',
        value: '',
    },
    {
        label: 'Customer requested a refund',
        value: 'customer_request',
    },
    {
        label: 'Customer was double-charged',
        value: 'duplicate',
    },
    {
        label: 'Payment was reported as fraud',
        value: 'fraudulent',
    }
];

const makePostRefund = ({ authToken, accountId, paymentId, service }) => async ({ refundBody, onSuccess, onError, final }) => {
    var _a;
    try {
        const response = await service.postRefund(paymentId, accountId, authToken, refundBody);
        if (!response.error) {
            onSuccess(response);
        }
        else {
            const responseError = getErrorMessage(response.error);
            const code = getErrorCode((_a = response.error) === null || _a === void 0 ? void 0 : _a.code);
            return onError({
                error: responseError,
                code,
                severity: ComponentErrorSeverity.ERROR,
            });
        }
    }
    catch (error) {
        const code = getErrorCode(error === null || error === void 0 ? void 0 : error.code);
        return onError({
            error: error.message || error,
            code,
            severity: ComponentErrorSeverity.ERROR,
        });
    }
    finally {
        final();
    }
};

const api$1 = Api();
class RefundService {
    async postRefund(paymentId, accountId, authToken, refundBody) {
        const endpoint = `payments/${paymentId}/refunds`;
        const headers = { 'Sub-Account': accountId };
        const body = refundBody;
        return api$1.post({ endpoint, headers, body, authToken });
    }
}

const makePostVoid = ({ authToken, accountId, paymentId, service }) => async ({ onSuccess, onError, final }) => {
    var _a;
    try {
        const response = await service.postVoid(paymentId, accountId, authToken);
        if (!response.error) {
            onSuccess(response);
        }
        else {
            const responseError = getErrorMessage(response.error);
            const code = getErrorCode((_a = response.error) === null || _a === void 0 ? void 0 : _a.code);
            return onError({
                error: responseError,
                code,
                severity: ComponentErrorSeverity.ERROR,
            });
        }
    }
    catch (error) {
        const code = getErrorCode(error === null || error === void 0 ? void 0 : error.code);
        return onError({
            error: error.message || error,
            code,
            severity: ComponentErrorSeverity.ERROR,
        });
    }
    finally {
        final();
    }
};

const api = Api();
class VoidService {
    async postVoid(paymentId, accountId, authToken) {
        const endpoint = `payments/${paymentId}/void`;
        const headers = { 'Sub-Account': accountId };
        return api.post({ endpoint, headers, authToken });
    }
}

const FormBlock = () => (h("div", { class: "row gap-3" }, h("div", { class: "col-12" }, h(Skeleton, { width: "100%", height: "40px" }))));
const RefundLoading = () => {
    return (h(StyledHost, null, h("div", { class: "row gap-5" }, h(FormBlock, null), h(FormBlock, null), h(FormBlock, null))));
};

const JustifiRefundPayment$1 = /*@__PURE__*/ proxyCustomElement(class JustifiRefundPayment extends HTMLElement {
    constructor(registerHost) {
        super();
        if (registerHost !== false) {
            this.__registerHost();
        }
        this.__attachShadow();
        this.errorEvent = createEvent(this, "error-event", 7);
        this.submitEvent = createEvent(this, "submit-event", 7);
        this.refundPayload = {};
        this.displayAmount = '';
        this.errors = {};
        this.paymentLoading = true;
        this.refundLoading = false;
        this.hideSubmitButton = false;
        this.inputHandler = (name, value) => {
            this.formController.setValues(Object.assign(Object.assign({}, this.formController.values.getValue()), { [name]: value }));
        };
    }
    componentWillLoad() {
        checkPkgVersion();
        this.analytics = new JustifiAnalytics(this);
        this.initializeApi();
        this.formController = new FormController(RefundPaymentSchema());
    }
    handleError(code, errorMessage, severity) {
        this.errorEvent.emit({ errorCode: code, message: errorMessage, severity });
    }
    checkAmount(amount) {
        return amount > 0;
    }
    handleInvalidAmount() {
        this.submitDisabled = true;
        const errorMessage = 'Refund amount must be greater than 0';
        this.handleError(ComponentErrorCodes.INVALID_REFUND_AMOUNT, errorMessage, ComponentErrorSeverity.ERROR);
    }
    isPaymentCreatedWithin25Minutes() {
        var _a;
        if (!this.payment || !((_a = this.payment) === null || _a === void 0 ? void 0 : _a.created_at)) {
            return false;
        }
        const paymentCreatedAt = new Date(this.payment.created_at);
        const now = new Date();
        const diffInMinutes = (now.getTime() - paymentCreatedAt.getTime()) / (1000 * 60);
        return diffInMinutes <= 25;
    }
    initializeFormController() {
        const amount = this.refundPayload.amount;
        const amountRefundable = amount ? amount.toString() : '0';
        this.formController = new FormController(RefundPaymentSchema(amountRefundable));
        this.formController.setInitialValues({
            amount: amountRefundable
        });
        this.formController.values.subscribe(values => {
            this.refundPayload = Object.assign({}, values);
        });
        this.formController.errors.subscribe(errors => {
            this.errors = Object.assign({}, errors);
        });
    }
    initializeApi() {
        if (this.paymentId && this.authToken) {
            const getPayment = makeGetPaymentDetails({
                id: this.paymentId,
                authToken: this.authToken,
                service: new PaymentService()
            });
            getPayment({
                onSuccess: ({ payment }) => {
                    this.payment = payment;
                    this.refundPayload = new RefundPayload({ amount: payment.amount_refundable });
                },
                onError: ({ error, code, severity }) => {
                    this.handleError(code, error, severity);
                },
                final: () => {
                    const amount = this.refundPayload.amount;
                    const validAmount = this.checkAmount(amount);
                    !validAmount ? this.handleInvalidAmount() : this.initializeFormController();
                    this.paymentLoading = false;
                }
            });
        }
        else {
            const errorMessage = 'Payment ID and Auth Token are required';
            this.handleError(ComponentErrorCodes.MISSING_PROPS, errorMessage, ComponentErrorSeverity.ERROR);
        }
    }
    async refundPayment(event) {
        event && event.preventDefault();
        const valid = await this.formController.validate();
        if (!valid)
            return;
        const values = this.formController.values.getValue();
        this.refundLoading = true;
        // Check if payment was created within 25 minutes and try to void first
        if (this.isPaymentCreatedWithin25Minutes()) {
            return this.tryVoidPayment();
        }
        // Otherwise, proceed with refund
        return this.processRefund(values);
    }
    async tryVoidPayment() {
        const postVoid = makePostVoid({
            authToken: this.authToken,
            accountId: this.accountId,
            paymentId: this.paymentId,
            service: new VoidService()
        });
        return new Promise((resolve) => {
            let voidResponse;
            let voidAttempted = false;
            const values = this.formController.values.getValue();
            postVoid({
                onSuccess: (response) => {
                    voidResponse = response;
                    voidAttempted = true;
                },
                onError: ({ error, code, severity }) => {
                    // If void fails, fall back to refund
                    voidAttempted = true;
                    this.handleError(error, code, severity);
                    this.processRefund(values)
                        .then(resolve);
                },
                final: () => {
                    if (voidResponse && !voidResponse.error && voidAttempted) {
                        this.submitEvent.emit({ response: voidResponse });
                        this.submitDisabled = true;
                        this.refundLoading = false;
                        resolve(voidResponse.data);
                    }
                },
            });
        });
    }
    async processRefund(values) {
        const postRefund = makePostRefund({
            authToken: this.authToken,
            accountId: this.accountId,
            paymentId: this.paymentId,
            service: new RefundService()
        });
        return new Promise((resolve) => {
            let refundResponse;
            postRefund({
                refundBody: values,
                onSuccess: (response) => { refundResponse = response; },
                onError: ({ error, code, severity }) => {
                    refundResponse = error;
                    this.handleError(error, code, severity);
                },
                final: () => {
                    this.submitEvent.emit({ response: refundResponse });
                    this.submitDisabled = true;
                    this.refundLoading = false;
                    resolve(refundResponse.data);
                },
            });
        });
    }
    render() {
        if (this.paymentLoading) {
            return h(RefundLoading, null);
        }
        const defaultValues = this.formController.getInitialValues();
        const currentRefundAmount = this.refundPayload.amount;
        return (h(StyledHost, null, h("form", null, h("fieldset", null, h("div", { class: "row gy-3" }, h("div", { class: "col-12" }, h("form-control-monetary", { name: "amount", label: "Refund Amount", defaultValue: defaultValues.amount, inputHandler: this.inputHandler, errorText: this.errors.amount })), h("div", { class: "col-12" }, h("form-control-select", { name: "reason", label: "Reason for refund (optional)", defaultValue: defaultValues.reason, inputHandler: this.inputHandler, options: refundReasonOptions, errorText: this.errors.reason })), h("div", { class: "col-12" }, h("form-control-textarea", { name: "description", label: "Note (optional)", defaultValue: defaultValues.description, inputHandler: this.inputHandler, maxLength: 250, errorText: this.errors.description })), h("div", { class: "form-group d-flex flex-row-reverse" }, h(Button, { variant: "primary", type: "submit", onClick: this.refundPayment.bind(this), isLoading: this.paymentLoading || this.refundLoading, hidden: this.hideSubmitButton, disabled: this.submitDisabled }, `Refund ${formatCurrency(+currentRefundAmount)}`)))))));
    }
}, [257, "justifi-refund-payment", {
        "authToken": [1, "auth-token"],
        "accountId": [1, "account-id"],
        "paymentId": [1, "payment-id"],
        "hideSubmitButton": [4, "hide-submit-button"],
        "formController": [32],
        "refundPayload": [32],
        "displayAmount": [32],
        "errors": [32],
        "paymentLoading": [32],
        "refundLoading": [32],
        "submitDisabled": [32],
        "payment": [32],
        "refundPayment": [64]
    }]);
function defineCustomElement$1() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["justifi-refund-payment", "custom-popper", "form-control-help-text", "form-control-monetary", "form-control-select", "form-control-textarea", "form-control-tooltip"];
    components.forEach(tagName => { switch (tagName) {
        case "justifi-refund-payment":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, JustifiRefundPayment$1);
            }
            break;
        case "custom-popper":
            if (!customElements.get(tagName)) {
                defineCustomElement$7();
            }
            break;
        case "form-control-help-text":
            if (!customElements.get(tagName)) {
                defineCustomElement$6();
            }
            break;
        case "form-control-monetary":
            if (!customElements.get(tagName)) {
                defineCustomElement$5();
            }
            break;
        case "form-control-select":
            if (!customElements.get(tagName)) {
                defineCustomElement$4();
            }
            break;
        case "form-control-textarea":
            if (!customElements.get(tagName)) {
                defineCustomElement$3();
            }
            break;
        case "form-control-tooltip":
            if (!customElements.get(tagName)) {
                defineCustomElement$2();
            }
            break;
    } });
}
defineCustomElement$1();

const JustifiRefundPayment = JustifiRefundPayment$1;
const defineCustomElement = defineCustomElement$1;

export { JustifiRefundPayment, defineCustomElement };
