<template>
    <Form>
        <div class="container-fluid fade-on-route-transition">
            <div class="row justify-content-center">
                <div class="col-md-6 px-0 px-md-2">
                    <siteHeader cmsWidgetName="SiteHeaderWidget" />
                </div>
            </div>
            <div class="row justify-content-center">
                <div class="col-md-6 col-xl-4">
                    <alert
                        v-if="displayPayInAdvanceCreditCardAlert"
                        name="payInAdvanceCreditCardErrorAlert"
                        class="my-4"
                        cmsWidgetName="PayInAdvanceCreditCardErrorAlertWidget"
                        alertClass="alert-danger"
                        :isDismissible="false"
                        @textLinkClicked="paymentFailedPayLater" />
                    <alert
                        v-if="displayPayInAdvanceAfterPayAlert"
                        name="payInAdvanceAfterPayErrorAlert"
                        class="my-4"
                        cmsWidgetName="PayInAdvanceAfterpayErrorAlertWidget"
                        alertClass="alert-danger"
                        :isDismissible="false"
                        @textLinkClicked="paymentFailedPayLater" />

                    <div id="card-container">
                        <iframe
                            id="card-frame"
                            ref="paymentFrame"
                            v-resize
                            class="hop-iframe payment-iframe"
                            name="card-frame"
                            seamless
                            scrolling="no"
                            allow="payment *; microphone *; geolocation *;">
                        </iframe>
                    </div>

                    <div
                        class="px-2">
                        <hr :class="{'my-0': isCreditCard}">
                        <cartDropdown
                            ref="cart"
                            :readOnly="true"
                            :showDropdownHeader="true"
                            :isInitiallyExpanded="true"
                            recyclingModalCmsWidgetName="RecycleModal"
                            servicePackageTitleWidgetName="ServicePackageTitle" />
                        <hr class="my-0">
                    </div>

                    <siteFooter
                        ref="siteFooter"
                        cmsWidgetName="SiteFooterWidget"
                        :isForwardActionDisabled="true"
                        :isForwardButtonHidden="true"
                        @ForwardClicked="forwardButtonAction"
                        @backClicked="backButtonAction" />
                </div>
            </div>
            <div
                v-if="shouldBlockInteraction"
                class="ui-block"
                @click="supressClick"></div>
        </div>
    </Form>

    <form
        id="card-data"
        ref="hopForm"
        :target="isPaypal ? '_top' : 'card-frame'"
        method="POST"
        :action="checkoutUrl">
        <input
            type="hidden"
            name="sgSessionId"
            :value="authToken" />
        <input
            type="hidden"
            name="sgAuthToken"
            :value="authToken" />
        <input
            type="hidden"
            name="sgSignaturePublic"
            :value="authSignature" />
        <input
            type="hidden"
            name="sgSignatureStartDate"
            :value="authSignatureStart" />
        <input
            type="hidden"
            name="referralSeqNum"
            :value="referralSequenceNumber" />
        <input
            type="hidden"
            name="sge_commerce_indicator_isinternet"
            value="true" />
        <input
            type="hidden"
            name="sghopsource"
            value="Safelite.com" />
        <input
            type="hidden"
            name="sgHtmlStyle"
            value="ResourceSafeliteHtml" />
        <input
            type="hidden"
            name="sgErrorMessagesEmbedded"
            value="true" />
        <input
            type="hidden"
            name="sgNoKeystrokeProcessing"
            value="false" />
        <input
            type="hidden"
            name="maskCharacter"
            value="*" />
        <input
            type="hidden"
            name="styleSheetCode"
            :value="dynamicCSSUrl" />
        <input
            type="hidden"
            name="styleSheetCode2"
            :value="dynamicHopCSSUrl" />
        <input
            type="hidden"
            name="sgReceiptResponseURL"
            :value="payInAdvanceResponseUrl" />
        <input
            type="hidden"
            name="sgDeclineResponseURL"
            :value="payInAdvanceResponseUrl" />
        <input
            type="hidden"
            name="sgErrorResponseURL"
            :value="payInAdvanceResponseUrl" />
        <input
            type="hidden"
            name="sgheaderline1"
            :value="getHeaderLine1" />
        <input
            type="hidden"
            name="sgHeader1subtitle"
            value="" />
        <input
            type="hidden"
            name="sgheaderline2"
            :value="getHeaderLine2" />
        <input
            type="hidden"
            name="sgheaderline3"
            value="" />
        <input
            type="hidden"
            name="sgheaderline4"
            value="" />
        <input
            type="hidden"
            name="sgheaderline5"
            value="*Required information" />
        <input
            type="hidden"
            name="billTo_firstName"
            :value="firstName" />
        <input
            type="hidden"
            name="billTo_firstNameShow"
            value="true" />
        <input
            type="hidden"
            name="sghopmiddleInitialShow"
            value="false" />
        <input
            type="hidden"
            name="billTo_lastName"
            :value="lastName" />
        <input
            type="hidden"
            name="billTo_lastNameShow"
            value="true" />
        <input
            type="hidden"
            name="billTo_street1"
            value="" />
        <input
            type="hidden"
            name="billTo_street2"
            value="" />
        <input
            type="hidden"
            name="billTo_city"
            value="" />
        <input
            type="hidden"
            name="billTo_state"
            value="" />
        <input
            type="hidden"
            name="billTo_postalCode"
            value="" />
        <input
            type="hidden"
            name="billTo_postalCodeShow"
            value="true" />
        <input
            type="hidden"
            name="billTo_postalCodeEnable"
            value="true" />
        <input
            type="hidden"
            name="sgLabelPostalCode"
            value="Billing ZIP" />
        <input
            type="hidden"
            name="sgtotalamount"
            :value="displayAmount" />
        <input
            type="hidden"
            name="totalAmountDecimal"
            :value="totalAmount" />
        <input
            type="hidden"
            name="lineItems"
            :value="payInAdvanceLineItems" />
        <input
            type="hidden"
            name="sgdiscountstrikethruamount"
            value="" />
        <input
            type="hidden"
            name="callerDisplayText"
            value="" />
        <input
            type="hidden"
            name="sgtermsofusedisplaytext"
            value="By selecting submit, I agree to Safelite's" />
        <input
            type="hidden"
            name="sgtermsofuseurl"
            value="http://www.safelite.com/terms-of-use/" />
        <input
            type="hidden"
            name="sgtermsofuselinkdisplaytext"
            value="terms of use" />
        <input
            type="hidden"
            name="sgtermsofcancelrefunddisplaytext"
            value="and" />
        <input
            type="hidden"
            name="sgtermsofcancelrefundlinkdisplaytext"
            value="cancellation and refund policy" />
        <input
            type="hidden"
            name="sgtermsofcancelrefundurl"
            value="http://www.safelite.com/cancellation-refund-policy" />
        <input
            type="hidden"
            name="sgErrorMessageCardVerification"
            value="Credit card could not be processed" />
        <input
            type="hidden"
            name="sgErrorMessageTimeOut"
            value="For your security, this transaction has been timed out." />
        <input
            type="hidden"
            name="sgLabelCardNumber"
            value="" />
        <input
            type="hidden"
            name="sgLabelAddressLine1"
            :value="address1" />
        <input
            type="hidden"
            name="sgLabelAddressLine2"
            :value="address2" />
        <input
            type="hidden"
            name="sgLabelCity"
            :value="city" />
        <input
            type="hidden"
            name="sgLabelState"
            :value="state" />
        <input
            type="hidden"
            name="sgCtu"
            :value="ctu" />
        <input
            type="hidden"
            name="sgWorkOrder"
            :value="workOrderNumber" />
        <input
            type="hidden"
            name="sgEmailAddress"
            :value="emailAddress" />
        <input
            type="hidden"
            name="paypalInvoiceNumber"
            :value="invoiceNumber" />
        <input
            type="hidden"
            name="paypalSuccessUrl"
            :value="payInAdvanceResponseUrl" />
        <input
            type="hidden"
            name="paypalCancelUrl"
            :value="payInAdvanceCancelUrl" />
        <input
            type="hidden"
            name="sgCCDeclineURL"
            :value="payInAdvanceCancelUrl" />
        <input
            type="hidden"
            name="sgCCTimeoutURL"
            :value="payInAdvanceCancelUrl" />
        <input
            type="hidden"
            name="sgTransactionType"
            value="authorization" />
        <input
            type="hidden"
            name="amount"
            :value="totalAmount" />
        <input
            type="hidden"
            name="ctu"
            :value="ctu" />
        <input
            type="hidden"
            name="orderNumber"
            :value="workOrderNumber" />
        <input
            type="hidden"
            name="billTo_email"
            :value="emailAddress" />
        <input
            type="hidden"
            name="useDecisionManager"
            value="True" />
        <input
            type="hidden"
            name="correlationId"
            :value="referralCorrelationId" />
        <input
            type="hidden"
            name="sgErrorMessageCard_CVN"
            value="Please enter a valid CVV" />
        <input
            type="hidden"
            name="ship_to_address_line1"
            :value="address1" />
        <input
            type="hidden"
            name="ship_to_address_line2"
            :value="address2" />
        <input
            type="hidden"
            name="ship_to_address_city"
            :value="city" />
        <input
            type="hidden"
            name="ship_to_address_state"
            :value="state" />
        <input
            type="hidden"
            name="ship_to_address_country"
            value="US" />
        <input
            type="hidden"
            name="ship_to_address_postal_code"
            :value="zipCode" />
        <input
            type="hidden"
            name="ship_to_phone"
            :value="phoneNumber" />
        <input
            type="hidden"
            name="calling_application"
            value="ISSNextGen" />

        <input type="hidden"
               name="parentdomainname"
               :value="parentNomainName" />
    </form>
</template>
<script>
// Components
import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';

// Supporting files
import issPageValues from '@/router/router-constants/issPage-values.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper';
import { Form } from 'vee-validate';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { getCartTotal } from '@/helpers/cart-helper';
import { useMainStore } from '@/store';
import iframeResize from 'iframe-resizer/js/iframeResizer.js';
import externalUrls from '@/router/router-constants/externalUrl-values.js';
import widgetFields from '@/constants/cms-widget-fields.js';
import { paymentMethods } from '@/constants/payment-method-constants.js';
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
import queryStrings from '@/constants/query-strings';
import alert from '@/ux-components/alert/alert.vue';
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
import { formatAmountInDollars } from '@/helpers/text-helper';

export default {
    name: 'payment-page',
    components: {
        cartDropdown,
        siteHeader,
        siteFooter,
        // eslint-disable-next-line vue/no-reserved-component-names
        Form,
        alert
    },
    directives: {
        resize: {
            mounted(el) {
                el.addEventListener('load', () => {
                    iframeResize({ checkOrigin: false }, el);
                });
            },
            unmounted(el) {
                el.iFrameResizer.removeListeners();
            }
        }
    },
    mixins: [BaseFormMixin],
    async beforeRouteEnter(to, from, next) {
        // Call APIs
        const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);

        const paymentSignaturePromise = await useMainStore().getPaymentSignature();

        // Settle promises and get results
        const promiseResultMap = [
            {
                resultKey: 'cmsContent',
                promise: cmsContentPromise
            },
            {
                resultKey: 'paymentSignature',
                promise: paymentSignaturePromise
            }
        ];

        // use resultMap to populate layout content.
        const resultMap = await settleAllPromises(promiseResultMap);

        next((vm) => {
            vm.setCmsContent(resultMap.cmsContent);
            vm.$nextTick(() => {
                if (vm.$refs.cart) {
                    const cartItems = vm.$refs.cart.allCartItems;
                    vm.getPayInAdvanceLineItems(cartItems);
                }

                vm.fetchSignatureInfo(resultMap.paymentSignature);
                vm.setIFrameListener();
            });
        });
    },
    setup() {
        const mainStore = useMainStore();
        return { mainStore };
    },
    data() {
        return {
            checkoutUrl: externalUrls.SAFELITE_HOP,
            paymentType: useMainStore().order.payment.paymentMethod,
            authToken: '',
            authSignature: '',
            authSignatureStart: '',
            referralSequenceNumber: useMainStore().order.referralSequenceNumber,
            emailAddress: useMainStore().order.contactInfo.emailAddress,
            address1: this.getAddress1(),
            address2: this.getAddress2(),
            city: this.getCity(),
            state: this.getState(),
            zipCode: this.getZipCode(),
            firstName: useMainStore().order.contactInfo.firstName,
            lastName: useMainStore().order.contactInfo.lastName,
            phoneNumber: useMainStore().order.contactInfo.servicePhone,
            ctu: useMainStore().order.serviceLocation.zipCodeCtu,
            referralCorrelationId: useMainStore().order.referralCorrelationId,
            workOrderNumber: this.getWorkOrderNumber(),
            invoiceNumber: this.getInvoiceNumber(),
            totalAmount: this.getAmountDue(),
            displayAmount: this.getDisplayAmountDue(),
            payInAdvanceLineItems: '',
            shouldBlockInteraction: false
        };
    },
    computed: {
        parentNomainName() {
            return window.location.hostname;
        },
        payInAdvanceResponseUrl() {
            const { protocol, host } = window.location;
            return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_RETURN}&src=iss-nextgen`;
        },
        payInAdvanceCancelUrl() {
            const { protocol, host } = window.location;
            return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_METHOD}&src=iss-nextgen`;
        },
        dynamicCSSUrl() {
            const { protocol, hostname, port } = window.location;
            return `${protocol}//${hostname}:${port}/css/site-2020Styling.css`;
        },
        dynamicHopCSSUrl() {
            const { protocol, hostname, port } = window.location;
            return `${protocol}//${hostname}:${port}/css/hop-styling.css`;
        },
        getHeaderLine1() {
            if (!this.isPaypal) {
                return this.getCmsContent('PayInAdvanceHeaderLine1', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
            }
            return '';
        },
        getHeaderLine2() {
            if (!this.isPaypal) {
                return this.getCmsContent(
                    'PayInAdvanceHeaderLine2',
                    widgetFields.TEXT_BLOCK_WIDGET.TEXT
                );
            }
            return '';
        },
        isPaypal() {
            return this.paymentType === paymentMethods.PAYPAL;
        },
        isCreditCard() {
            return this.paymentType === paymentMethods.CREDIT_CARD;
        },
        isAfterPay() {
            return this.paymentType === paymentMethods.AFTERPAY;
        },
        displayPayInAdvanceCreditCardAlert() {
            return this.displayPayInAdvanceAlert(paymentMethods.CREDIT_CARD);
        },
        displayPayInAdvanceAfterPayAlert() {
            return this.displayPayInAdvanceAlert(paymentMethods.AFTERPAY);
        }
    },
    methods: {
        arePagePrerequisitesValid() {
            // Line Items
            const packageReqs =
                !!useMainStore().order.lineItems.supportingItems;

            // Service Location
            const { serviceLocation } = useMainStore().order;
            const mobileReqs = !!(
                serviceLocation.address
                && serviceLocation.city
                && serviceLocation.state
                && serviceLocation.zipCode
            );

            const providerLocation = serviceLocation.provider.address;
            const dropOffInshopReqs = !!(
                providerLocation.streetAddress
                && providerLocation.city
                && providerLocation.state
                && providerLocation.zipCode
            );

            const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
                || serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;

            const serviceLocationReqs =
                (isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);

            // Insurance
            const isInsuranceSet =
                useMainStore().order.payment.isInsurance !== null;

            // Schedule
            const { schedule } = useMainStore().order;
            const scheduleReqs = !!(
                schedule.date
                && schedule.startTime
                && schedule.endTime
                && schedule.jobMaxMinutes
                && schedule.jobMinMinutes
            );

            // Contact Info
            const { contactInfo } = useMainStore().order;
            const contactInfoReqs = !!(
                contactInfo.firstName
                && contactInfo.lastName
                && contactInfo.servicePhone
                && contactInfo.emailAddress
            );

            const paymentMethodReqs = useMainStore().isPayInAdvance;

            return (
                packageReqs
                && serviceLocationReqs
                && isInsuranceSet
                && scheduleReqs
                && contactInfoReqs
                && paymentMethodReqs
            );
        },
        getWorkOrderNumber() {
            const { workOrderNumber } = useMainStore().order;
            if (workOrderNumber) {
                const items = workOrderNumber.split('-');
                if (items.length > 1) {
                    return items[1];
                }
            }
            return undefined;
        },
        getInvoiceNumber() {
            const { workOrderNumber } = useMainStore().order;
            if (workOrderNumber) {
                return workOrderNumber.replace('-', '');
            }
            return undefined;
        },
        getAddress1() {
            return (
                useMainStore().order.serviceLocation.address
                ?? useMainStore().order.serviceLocation.provider.address
                    .streetAddress
            );
        },
        getAddress2() {
            return useMainStore().order.serviceLocation.address2;
        },
        getCity() {
            return (
                useMainStore().order.serviceLocation.city
                ?? useMainStore().order.serviceLocation.provider.address.city
            );
        },
        getState() {
            return (
                useMainStore().order.serviceLocation.state
                ?? useMainStore().order.serviceLocation.provider.address.state
            );
        },
        getZipCode() {
            return (
                useMainStore().order.serviceLocation.zipCode
                ?? useMainStore().order.serviceLocation.provider.address.zipCode
            );
        },
        getPayInAdvanceLineItems(cartItems) {
            const { glassParts } = useMainStore().order.lineItems;
            const lineItems =
                glassParts === null
                    ? [
                        this.getPayInAdvanceFormattedLineItem('Labor', 0, 1),
                        this.getPayInAdvanceFormattedLineItem('Repair supplies', 0, 1)
                    ]
                    : [
                        this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1)
                    ];

            cartItems.forEach((item) => {
                if (item.name !== null && item.category !== 'promos') {
                    lineItems.push(this.getPayInAdvanceFormattedLineItem(
                        item.name,
                        (item.salesTax + item.subTotal).toFixed(2),
                        1
                    ));
                }
            });

            this.payInAdvanceLineItems = lineItems.join('||');
        },
        getPayInAdvanceFormattedLineItem(itemName, price, quantity) {
            return `${itemName}|${price}|${quantity}`;
        },
        getAmountDue() {
            return getCartTotal(useMainStore().order);
        },
        getDisplayAmountDue() {
            return formatAmountInDollars(this.getAmountDue());
        },
        fetchSignatureInfo(signatureInfo) {
            this.authToken = signatureInfo.token;
            this.authSignature = signatureInfo.signature;
            this.authSignatureStart = signatureInfo.startDate;

            this.submitHopForm();
        },
        submitHopForm() {
            this.$nextTick(() => {
                this.$refs.hopForm.submit();

                const iframe = this.$refs.paymentFrame;
                if (iframe) {
                    iframe.onload = () => {
                        if (iframe.contentWindow) {
                            iframe.contentWindow.postMessage('hybrid', '*');

                            if (this.isAfterPay) {
                                iframe.contentWindow.postMessage('afterpay', '*');
                            } else {
                                iframe.contentWindow.postMessage('CreditCardChosen', '*');
                            }
                        }
                    };
                }
            });
        },
        handleIFrameContentWindowMessage(event) {
            if (typeof event.data !== 'string') {
                return;
            }

            if (event.data.includes('afterpayClosed')) {
                this.backButtonAction();
            }

            if (useMainStore().order.payment.paymentMethod !== paymentMethods.PayNow) {
                return;
            }

            if (event.data.includes('creditCardSubmit')) {
                useMainStore().savePaymentMethodChoice(paymentMethods.CREDIT_CARD);
                this.setUIBlock(true);
            }
            if (event.data.includes('afterpayPaymentReceived')) {
                useMainStore().savePaymentMethodChoice(paymentMethods.AFTERPAY);
            }
            if (event.data.includes('applepayOpened')) {
                useMainStore().savePaymentMethodChoice(paymentMethods.APPLEPAY);
            }
            if (event.data.includes('showLoaderForPaypal')) {
                useMainStore().savePaymentMethodChoice(paymentMethods.PAYPAL);
            }
        },
        setIFrameListener() {
            window.addEventListener('message', this.handleIFrameContentWindowMessage);
        },
        setUIBlock(val) {
            this.shouldBlockInteraction = val;
        },
        supressClick(event) {
            if (this.shouldBlockInteraction) {
                event.stopPropagation();
            }
        },
        displayPayInAdvanceAlert(payMethod) {
            return (
                this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT] === payMethod
            );
        },
        paymentFailedPayLater() {
            this.$router.navigate(
                this.navigationScenarios.CLICKED_FORWARD,
                this.$route
            );
        },
        backButtonAction() {
            // page will not render with normal navigation due to navigating from the iframe
            window.location = this.payInAdvanceCancelUrl;
        },
        forwardButtonAction() {
            this.$router.navigate(
                this.navigationScenarios.CLICKED_FORWARD,
                this.$route
            );
        }
    }
};
</script>
<style lang="scss" scoped>
.container-fluid {
    &.fade-on-route-transition {
        height: unset;
    }
}

.payment p {
    margin-bottom: 0.75rem;
}

.hop-iframe {
    position: relative;
    min-height: 40.625rem;
    width: 100%;
    border: 0 none;
}

.ui-block {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 9999;
}
</style>
