import { h } from "@stencil/core";
import { makeGetCheckout } from "../../actions/checkout/checkout-actions";
import { CheckoutService } from "../../api/services/checkout.service";
import { CompletionStatuses, ICheckoutStatus } from "../../api/Checkout";
import { ComponentErrorCodes, ComponentErrorMessages, ComponentErrorSeverity } from "../../api/ComponentError";
import JustifiAnalytics from "../../api/Analytics";
import { checkPkgVersion } from "../../utils/check-pkg-version";
export class JustifiQrTerminal {
    constructor() {
        this.pollIntervalMs = 3000;
        this.pollTimeoutMs = 600000;
        this.terminalState = 'loading';
        this.paymentStatus = '';
        this.errorMessage = '';
        this.pollIntervalHandle = null;
        this.pollTimeoutHandle = null;
        this.failedDismissHandle = null;
        this.seenCompletionCreatedAts = new Set();
        this.inFlight = false;
    }
    componentWillLoad() {
        checkPkgVersion();
        this.analytics = new JustifiAnalytics(this);
        this.initialize();
    }
    disconnectedCallback() {
        var _a;
        this.stopAll();
        (_a = this.analytics) === null || _a === void 0 ? void 0 : _a.cleanup();
    }
    propChanged() {
        this.stopAll();
        this.initialize();
    }
    suppressInnerErrors(event) {
        // Suppress error-event bubbling from inner justifi-checkout-qr-code
        event.stopPropagation();
    }
    get effectivePollInterval() {
        return Math.max(1000, this.pollIntervalMs);
    }
    initialize() {
        if (!this.authToken || !this.checkoutId) {
            this.errorEvent.emit({
                message: 'authToken and checkoutId are required',
                errorCode: ComponentErrorCodes.MISSING_PROPS,
                severity: ComponentErrorSeverity.ERROR,
            });
            return;
        }
        this.terminalState = 'loading';
        this.getCheckout = makeGetCheckout({
            authToken: this.authToken,
            checkoutId: this.checkoutId,
            service: new CheckoutService(),
        });
        this.getCheckout({
            onSuccess: ({ checkout }) => this.handleInitialLoad(checkout),
            onError: ({ error, code, severity }) => {
                this.terminalState = 'error';
                this.errorMessage = error;
                this.errorEvent.emit({ message: error, errorCode: code, severity });
            },
        });
    }
    handleInitialLoad(checkout) {
        var _a;
        switch (checkout.status) {
            case ICheckoutStatus.expired:
                this.terminalState = 'expired';
                this.checkoutExpired.emit({ checkoutId: this.checkoutId });
                this.errorEvent.emit({
                    message: ComponentErrorMessages.CHECKOUT_EXPIRED,
                    errorCode: ComponentErrorCodes.CHECKOUT_EXPIRED,
                    severity: ComponentErrorSeverity.ERROR,
                });
                break;
            case ICheckoutStatus.completed:
                this.terminalState = 'completed';
                this.paymentStatus = this.resolvePaymentStatus(checkout);
                this.checkoutCompleted.emit({ checkoutId: this.checkoutId, paymentStatus: this.paymentStatus });
                break;
            default:
                ((_a = checkout.completions) !== null && _a !== void 0 ? _a : []).forEach((c) => this.seenCompletionCreatedAts.add(c.created_at));
                this.terminalState = 'ready';
                this.startPolling();
                break;
        }
    }
    startPolling() {
        this.pollTimeoutHandle = setTimeout(() => {
            this.stopAll();
            this.terminalState = 'error';
            this.errorMessage = 'Checkout polling timed out';
            this.errorEvent.emit({
                message: 'Checkout polling timed out',
                errorCode: ComponentErrorCodes.FETCH_ERROR,
                severity: ComponentErrorSeverity.ERROR,
            });
        }, this.pollTimeoutMs);
        this.pollIntervalHandle = setInterval(() => this.tick(), this.effectivePollInterval);
    }
    tick() {
        if (this.inFlight)
            return;
        this.inFlight = true;
        this.getCheckout({
            onSuccess: ({ checkout }) => {
                this.inFlight = false;
                this.handlePollResult(checkout);
            },
            onError: ({ error, code, severity }) => {
                this.inFlight = false;
                this.stopAll();
                this.terminalState = 'error';
                this.errorMessage = error;
                this.errorEvent.emit({ message: error, errorCode: code, severity });
            },
        });
    }
    handlePollResult(checkout) {
        var _a;
        const completions = (_a = checkout.completions) !== null && _a !== void 0 ? _a : [];
        const newFailures = completions.filter((c) => !this.seenCompletionCreatedAts.has(c.created_at) && c.payment_status === 'failed');
        newFailures.forEach((c) => this.seenCompletionCreatedAts.add(c.created_at));
        if (newFailures.length > 0) {
            this.terminalState = 'payment-failed';
            if (this.failedDismissHandle)
                clearTimeout(this.failedDismissHandle);
            this.failedDismissHandle = setTimeout(() => {
                if (this.terminalState === 'payment-failed')
                    this.terminalState = 'ready';
            }, 3000);
        }
        if (checkout.status === ICheckoutStatus.completed) {
            this.stopAll();
            this.terminalState = 'completed';
            this.paymentStatus = this.resolvePaymentStatus(checkout);
            this.checkoutCompleted.emit({ checkoutId: this.checkoutId, paymentStatus: this.paymentStatus });
            return;
        }
        if (checkout.status === ICheckoutStatus.expired) {
            this.stopAll();
            this.terminalState = 'expired';
            this.checkoutExpired.emit({ checkoutId: this.checkoutId });
            this.errorEvent.emit({
                message: ComponentErrorMessages.CHECKOUT_EXPIRED,
                errorCode: ComponentErrorCodes.CHECKOUT_EXPIRED,
                severity: ComponentErrorSeverity.ERROR,
            });
        }
    }
    resolvePaymentStatus(checkout) {
        var _a, _b;
        const completions = (_a = checkout.completions) !== null && _a !== void 0 ? _a : [];
        const sorted = [...completions].sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
        const latestStatus = (_b = sorted[0]) === null || _b === void 0 ? void 0 : _b.payment_status;
        if (latestStatus === CompletionStatuses.succeeded)
            return 'succeeded';
        if (latestStatus == null) {
            return checkout.successful_payment_id ? 'succeeded' : 'pending';
        }
        return 'pending';
    }
    stopAll() {
        if (this.pollIntervalHandle) {
            clearInterval(this.pollIntervalHandle);
            this.pollIntervalHandle = null;
        }
        if (this.pollTimeoutHandle) {
            clearTimeout(this.pollTimeoutHandle);
            this.pollTimeoutHandle = null;
        }
        if (this.failedDismissHandle) {
            clearTimeout(this.failedDismissHandle);
            this.failedDismissHandle = null;
        }
        this.inFlight = false;
    }
    render() {
        if (!this.authToken || !this.checkoutId)
            return null;
        return (h("div", null, this.terminalState === 'loading' && null, (this.terminalState === 'ready' || this.terminalState === 'payment-failed') && (h("div", null, h("justifi-checkout-qr-code", { checkoutId: this.checkoutId }), this.terminalState === 'payment-failed' && (h("p", null, "Payment failed. Please try again.")), this.terminalState === 'ready' && (h("p", null, "Scan to pay")))), this.terminalState === 'completed' && (h("div", null, this.paymentStatus === 'succeeded'
            ? h("p", null, "Payment received")
            : h("p", null, "Payment pending"))), this.terminalState === 'expired' && (h("p", null, "Checkout expired. Please create a new checkout.")), this.terminalState === 'error' && (h("p", null, this.errorMessage))));
    }
    static get is() { return "justifi-qr-terminal"; }
    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"
            },
            "checkoutId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "checkout-id"
            },
            "pollIntervalMs": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "poll-interval-ms",
                "defaultValue": "3000"
            },
            "pollTimeoutMs": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "poll-timeout-ms",
                "defaultValue": "600000"
            }
        };
    }
    static get states() {
        return {
            "terminalState": {},
            "paymentStatus": {},
            "errorMessage": {}
        };
    }
    static get events() {
        return [{
                "method": "checkoutCompleted",
                "name": "checkout-completed",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "{ checkoutId: string; paymentStatus: string }",
                    "resolved": "{ checkoutId: string; paymentStatus: string; }",
                    "references": {}
                }
            }, {
                "method": "checkoutExpired",
                "name": "checkout-expired",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": ""
                },
                "complexType": {
                    "original": "{ checkoutId: string }",
                    "resolved": "{ checkoutId: string; }",
                    "references": {}
                }
            }, {
                "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/ComponentEvents",
                            "id": "src/api/ComponentEvents.ts::ComponentErrorEvent"
                        }
                    }
                }
            }];
    }
    static get watchers() {
        return [{
                "propName": "authToken",
                "methodName": "propChanged"
            }, {
                "propName": "checkoutId",
                "methodName": "propChanged"
            }];
    }
    static get listeners() {
        return [{
                "name": "error-event",
                "method": "suppressInnerErrors",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
