import { h } from "@stencil/core";
import RefundPaymentSchema from "./refund-payment-schema";
import { ComponentErrorCodes, ComponentErrorSeverity, RefundPayload } from "../../api";
import { FormController } from "../../ui-components/form/form";
import { Button, StyledHost } from "../../ui-components";
import { formatCurrency } from "../../utils/utils";
import refundReasonOptions from "./refund-reason-options";
import { PaymentService } from "../../api/services/payment.service";
import { makeGetPaymentDetails } from "../../actions/payment/get-payment-details";
import JustifiAnalytics from "../../api/Analytics";
import { checkPkgVersion } from "../../utils/check-pkg-version";
import { makePostRefund } from "../../actions/refund/refund-actions";
import { RefundService } from "../../api/services/refund.service";
import { makePostVoid } from "../../actions/void/void-actions";
import { VoidService } from "../../api/services/void.service";
import { RefundLoading } from "./refund-loading";
export class JustifiRefundPayment {
    constructor() {
        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)}`)))))));
    }
    static get is() { return "justifi-refund-payment"; }
    static get encapsulation() { return "shadow"; }
    static get properties() {
        return {
            "authToken": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "auth-token"
            },
            "accountId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "account-id"
            },
            "paymentId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "payment-id"
            },
            "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",
                "defaultValue": "false"
            }
        };
    }
    static get states() {
        return {
            "formController": {},
            "refundPayload": {},
            "displayAmount": {},
            "errors": {},
            "paymentLoading": {},
            "refundLoading": {},
            "submitDisabled": {},
            "payment": {}
        };
    }
    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 {
            "refundPayment": {
                "complexType": {
                    "signature": "(event?: CustomEvent) => Promise<IRefund | IPayment>",
                    "parameters": [{
                            "name": "event",
                            "type": "CustomEvent<any>",
                            "docs": ""
                        }],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        },
                        "IPayment": {
                            "location": "import",
                            "path": "../../api",
                            "id": "src/api/index.ts::IPayment"
                        },
                        "IRefund": {
                            "location": "import",
                            "path": "../../api",
                            "id": "src/api/index.ts::IRefund"
                        },
                        "CustomEvent": {
                            "location": "global",
                            "id": "global::CustomEvent"
                        }
                    },
                    "return": "Promise<IPayment | IRefund>"
                },
                "docs": {
                    "text": "",
                    "tags": []
                }
            }
        };
    }
}
