import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
import { B as Button } from './button.js';
import { S as StyledHost } from './styled-host.js';
import { z as buttonPrimary } from './parts.js';
import './justifi-details2.js';
import './event-types.js';
import './justifi-radio-list-item2.js';
import { P as PlaidService } from './plaid.service.js';
import { P as PLAID_ERROR_SEVERITY, b as PLAID_ERROR_MESSAGES, c as PlaidErrorCodes, C as ComponentErrorSeverity } from './Plaid.js';

const PlaidVerification = /*@__PURE__*/ proxyCustomElement(class PlaidVerification extends HTMLElement {
    constructor(registerHost) {
        super();
        if (registerHost !== false) {
            this.__registerHost();
        }
        this.plaidVerificationSuccess = createEvent(this, "plaidVerificationSuccess", 7);
        this.plaidVerificationError = createEvent(this, "plaidVerificationError", 7);
        this.linkToken = null;
        this.linkTokenId = null;
        this.plaidLink = null;
        this.isAuthenticating = false;
        this.isSuccess = false;
        this.error = null;
        this.isLoading = false;
        this.plaidService = new PlaidService();
        this.abortController = null;
        this.timeoutId = null;
        this.initializePlaidLink = async () => {
            try {
                // Check if Plaid is available globally
                if (typeof window.Plaid === 'undefined') {
                    this.handleError({
                        code: PlaidErrorCodes.PLAID_SDK_LOAD_FAILED,
                        message: PLAID_ERROR_MESSAGES[PlaidErrorCodes.PLAID_SDK_LOAD_FAILED],
                        severity: PLAID_ERROR_SEVERITY[PlaidErrorCodes.PLAID_SDK_LOAD_FAILED],
                        retryable: true,
                        userAction: 'Refresh the page and try again',
                    });
                    return;
                }
                // Get link token from backend
                await this.getLinkToken();
                if (!this.linkToken) {
                    this.handleError({
                        code: PlaidErrorCodes.PLAID_LINK_TOKEN_FAILED,
                        message: PLAID_ERROR_MESSAGES[PlaidErrorCodes.PLAID_LINK_TOKEN_FAILED],
                        severity: PLAID_ERROR_SEVERITY[PlaidErrorCodes.PLAID_LINK_TOKEN_FAILED],
                        retryable: true,
                        userAction: 'Click to try again',
                    });
                    return;
                }
                // Initialize Plaid Link
                const Plaid = window.Plaid;
                this.plaidLink = Plaid.create({
                    token: this.linkToken,
                    onSuccess: this.handlePlaidSuccess,
                    onExit: this.handlePlaidExit,
                    onEvent: this.handlePlaidEvent,
                    onLoad: this.handlePlaidLoad,
                });
            }
            catch (error) {
                this.handleError({
                    code: PlaidErrorCodes.PLAID_LINK_INIT_FAILED,
                    message: PLAID_ERROR_MESSAGES[PlaidErrorCodes.PLAID_LINK_INIT_FAILED],
                    severity: PLAID_ERROR_SEVERITY[PlaidErrorCodes.PLAID_LINK_INIT_FAILED],
                    originalError: error,
                    retryable: true,
                    userAction: 'Click to try again',
                });
            }
        };
        this.getLinkToken = async () => {
            var _a, _b, _c, _d;
            try {
                if (!this.authToken || !this.accountId) {
                    this.handleError({
                        code: PlaidErrorCodes.PLAID_LINK_TOKEN_FAILED,
                        message: 'Missing authentication. Please provide authToken and accountId.',
                        severity: ComponentErrorSeverity.ERROR,
                        retryable: false,
                        userAction: 'Provide required props',
                    });
                    return;
                }
                // Create abort controller for timeout handling
                this.abortController = new AbortController();
                // Set timeout for the request
                this.timeoutId = setTimeout(() => {
                    var _a;
                    (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
                }, 30000); // 30 second timeout
                const response = await this.plaidService.getLinkTokenForVerification(this.authToken, this.businessId, this.abortController.signal);
                // Clear timeout
                if (this.timeoutId) {
                    clearTimeout(this.timeoutId);
                    this.timeoutId = null;
                }
                if (response.error) {
                    const errorMessage = typeof response.error === 'string'
                        ? response.error
                        : response.error.message || 'Failed to get link token';
                    throw new Error(errorMessage);
                }
                this.linkToken = response.data.link_token;
                this.linkTokenId = response.data.id;
            }
            catch (error) {
                // Clear timeout
                if (this.timeoutId) {
                    clearTimeout(this.timeoutId);
                    this.timeoutId = null;
                }
                let errorCode = PlaidErrorCodes.PLAID_LINK_TOKEN_FAILED;
                let message = PLAID_ERROR_MESSAGES[errorCode];
                let retryable = true;
                // Handle specific error types
                if (error.name === 'AbortError') {
                    errorCode = PlaidErrorCodes.PLAID_TIMEOUT;
                    message = PLAID_ERROR_MESSAGES[errorCode];
                    retryable = true;
                }
                else if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('network')) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('fetch'))) {
                    errorCode = PlaidErrorCodes.PLAID_NETWORK_ERROR;
                    message = PLAID_ERROR_MESSAGES[errorCode];
                    retryable = true;
                }
                else if (((_c = error.message) === null || _c === void 0 ? void 0 : _c.includes('401')) || ((_d = error.message) === null || _d === void 0 ? void 0 : _d.includes('unauthorized'))) {
                    errorCode = PlaidErrorCodes.PLAID_INVALID_CREDENTIALS;
                    message = 'Authentication failed. Please check your credentials.';
                    retryable = false;
                }
                this.handleError({
                    code: errorCode,
                    message: message,
                    severity: PLAID_ERROR_SEVERITY[errorCode],
                    originalError: error,
                    retryable,
                    userAction: retryable ? 'Click to try again' : 'Check your credentials',
                });
            }
        };
        this.openPlaidLink = () => {
            if (this.plaidLink && this.linkToken) {
                this.isAuthenticating = true;
                this.clearError();
                this.plaidLink.open();
            }
        };
        this.handlePlaidSuccess = async (publicToken, _metadata) => {
            var _a;
            this.isAuthenticating = false;
            this.isLoading = true;
            this.clearError();
            try {
                // Send publicToken to backend
                const response = await this.plaidService.postPlaidVerifiedBankAccountData(this.authToken, this.businessId, { public_token: publicToken, link_token_id: this.linkTokenId }, (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal);
                if (response.error) {
                    const errorMessage = typeof response.error === 'string'
                        ? response.error
                        : response.error.message || 'Failed to verify bank account';
                    throw new Error(errorMessage);
                }
                // Success - display success message
                this.isSuccess = true;
                this.isLoading = false;
                // Emit success event
                this.plaidVerificationSuccess.emit({ publicToken, bankAccount: response.data });
            }
            catch (error) {
                this.isLoading = false;
                this.handleError({
                    code: PlaidErrorCodes.PLAID_AUTHENTICATION_FAILED,
                    message: (error === null || error === void 0 ? void 0 : error.message) || 'Failed to verify bank account',
                    severity: PLAID_ERROR_SEVERITY[PlaidErrorCodes.PLAID_AUTHENTICATION_FAILED],
                    originalError: error,
                    retryable: true,
                    userAction: 'Click to try again',
                });
            }
        };
        this.handlePlaidExit = (err, _metadata) => {
            this.isAuthenticating = false;
            if (err) {
                this.handlePlaidError(err);
            }
        };
        this.handlePlaidEvent = (eventName, metadata) => {
            // Handle specific events if needed
            switch (eventName) {
                case 'OPEN':
                    this.isAuthenticating = true;
                    break;
                case 'CLOSE':
                    this.isAuthenticating = false;
                    break;
                case 'ERROR':
                    this.handlePlaidError(metadata);
                    break;
            }
        };
        this.handlePlaidLoad = () => {
            // Plaid Link loaded successfully
        };
        this.handlePlaidError = (error) => {
            let errorCode = PlaidErrorCodes.PLAID_AUTHENTICATION_FAILED;
            let message = PLAID_ERROR_MESSAGES[errorCode];
            let retryable = true;
            let userAction = 'Click to try again';
            // Map Plaid error codes to our error codes
            if (error.error_code) {
                switch (error.error_code) {
                    case 'INVALID_CREDENTIALS':
                        errorCode = PlaidErrorCodes.PLAID_INVALID_CREDENTIALS;
                        message = PLAID_ERROR_MESSAGES[errorCode];
                        retryable = true;
                        break;
                    case 'ITEM_LOGIN_REQUIRED':
                        errorCode = PlaidErrorCodes.PLAID_INVALID_CREDENTIALS;
                        message = 'Your bank requires re-authentication. Please try again.';
                        retryable = true;
                        break;
                    case 'ITEM_LOCKED':
                        errorCode = PlaidErrorCodes.PLAID_ACCOUNT_LOCKED;
                        message = PLAID_ERROR_MESSAGES[errorCode];
                        retryable = false;
                        userAction = 'Contact your bank';
                        break;
                    case 'INSTITUTION_NOT_RESPONDING':
                        errorCode = PlaidErrorCodes.PLAID_MAINTENANCE;
                        message = PLAID_ERROR_MESSAGES[errorCode];
                        retryable = true;
                        break;
                    case 'RATE_LIMIT_EXCEEDED':
                        errorCode = PlaidErrorCodes.PLAID_RATE_LIMITED;
                        message = PLAID_ERROR_MESSAGES[errorCode];
                        retryable = true;
                        break;
                    default:
                        if (error.error_message) {
                            message = error.error_message;
                        }
                        break;
                }
            }
            this.handleError({
                code: errorCode,
                message,
                severity: PLAID_ERROR_SEVERITY[errorCode],
                originalError: error,
                retryable,
                userAction,
            });
            this.isAuthenticating = false;
        };
        this.handleError = (plaidError) => {
            this.error = plaidError;
            this.isLoading = false;
            // Emit error event for parent components
            this.plaidVerificationError.emit(plaidError);
            console.error('Plaid verification error:', plaidError);
        };
        this.clearError = () => {
            if (this.error) {
                this.error = null;
            }
        };
    }
    componentDidRender() {
        if (!this.scriptRef)
            return;
        this.scriptRef.onload = () => {
            this.initializePlaidLink();
        };
        this.scriptRef.onerror = () => {
            this.handleError({
                code: PlaidErrorCodes.PLAID_SDK_LOAD_FAILED,
                message: PLAID_ERROR_MESSAGES[PlaidErrorCodes.PLAID_SDK_LOAD_FAILED],
                severity: PLAID_ERROR_SEVERITY[PlaidErrorCodes.PLAID_SDK_LOAD_FAILED],
                retryable: true,
                userAction: 'Refresh the page and try again',
            });
        };
    }
    disconnectedCallback() {
        // Clean up timeouts and abort controllers
        if (this.timeoutId) {
            clearTimeout(this.timeoutId);
        }
        if (this.abortController) {
            this.abortController.abort();
        }
    }
    render() {
        const renderErrorState = () => {
            if (!this.error)
                return null;
            const errorClass = this.error.severity === ComponentErrorSeverity.ERROR
                ? 'text-danger'
                : this.error.severity === ComponentErrorSeverity.WARNING
                    ? 'text-warning'
                    : 'text-info';
            return (h("div", { class: `${errorClass} mt-2` }, h("small", null, this.error.message), h("br", null), this.error.userAction && (h("small", { class: "text-muted" }, this.error.userAction))));
        };
        const renderStatusState = () => {
            if (this.error)
                return null;
            if (this.isLoading) {
                return (h("div", { class: "text-info mt-2" }, h("small", null, "Verifying bank account...")));
            }
            if (this.isSuccess) {
                return (h("div", { class: "text-success mt-2" }, h("small", null, "\u2713 Bank account verified successfully")));
            }
            if (this.isAuthenticating) {
                return (h("div", { class: "text-info mt-2" }, h("small", null, "Connecting to your bank...")));
            }
            return null;
        };
        const plaidLogo = (h("svg", { class: "plaid-logo-img", height: "20", width: "20", viewBox: "0 0 28 29", xmlns: "http://www.w3.org/2000/svg", style: { display: 'inline', marginLeft: '5px', marginRight: '5px', marginTop: '-2px' } }, h("g", { fill: "#fff", "fill-rule": "evenodd" }, h("path", { d: "M25.7629 26.2628L28 17.5309L24.9691 14.5001L27.9999 11.4691L25.7628 2.73706L17.0309 0.5L14.0001 3.531L10.969 0.50014L2.23706 2.73734L0 11.4691L3.03128 14.4999L0.00014 17.531L2.2372 26.2629L10.9691 28.5L14.0001 25.469L17.031 28.4999L25.7629 26.2628ZM15.7321 23.7371L18.6186 20.8505L22.2912 24.5233L17.6956 25.7007L15.7321 23.7371ZM11.1136 9.88154L14.0003 6.99502L16.8868 9.8814L14.0001 12.7679L11.1136 9.88154ZM12.2682 14.5L9.38154 17.3865L6.49502 14.5L9.38154 11.6135L12.2682 14.5ZM18.6187 11.6133L21.5053 14.5L18.6186 17.3865L15.7321 14.5L18.6187 11.6133ZM16.8867 19.1186L14.0001 22.0051L11.1135 19.1185L14.0001 16.2319L16.8867 19.1186ZM10.3044 25.7007L5.70864 24.5233L9.38154 20.8504L12.2682 23.7371L10.3044 25.7007ZM4.76308 16.2319L7.6496 19.1185L3.9767 22.7914L2.7993 18.1957L4.76308 16.2319ZM3.9767 6.20836L7.64974 9.8814L4.76308 12.7681L2.7993 10.8041L3.9767 6.20836ZM12.2683 5.26294L9.38168 8.1496L5.70892 4.4767L10.3047 3.2993L12.2683 5.26294ZM17.6959 3.2993L22.2915 4.4767L18.6186 8.14946L15.7321 5.26294L17.6959 3.2993ZM23.2372 12.7681L20.3505 9.8814L24.0233 6.20878L25.2007 10.8046L23.2372 12.7681ZM24.0233 22.7914L20.3505 19.1186L23.2372 16.2321L25.2007 18.1957L24.0233 22.7914Z" }))));
        return (h(StyledHost, null, h("script", { src: "https://cdn.plaid.com/link/v2/stable/link-initialize.js", async: true, ref: (el) => (this.scriptRef = el) }), h("div", null, h("div", { class: "mb-3" }, h(Button, { variant: "primary", type: "button", onClick: (event) => { event.preventDefault(); this.openPlaidLink(); }, disabled: this.isLoading, part: buttonPrimary }, "Connect with Plaid ", plaidLogo, " (instant verification)")), renderErrorState(), renderStatusState())));
    }
}, [256, "plaid-verification", {
        "authToken": [1, "auth-token"],
        "accountId": [1, "account-id"],
        "businessId": [1, "business-id"],
        "linkToken": [32],
        "linkTokenId": [32],
        "plaidLink": [32],
        "isAuthenticating": [32],
        "isSuccess": [32],
        "error": [32],
        "isLoading": [32]
    }]);
function defineCustomElement() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["plaid-verification"];
    components.forEach(tagName => { switch (tagName) {
        case "plaid-verification":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, PlaidVerification);
            }
            break;
    } });
}
defineCustomElement();

export { PlaidVerification as P, defineCustomElement as d };
