// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
 * @fileoverview 'settings-payments-section' is the section containing saved
 * credit cards for use in autofill and payments APIs.
 */
import 'chrome://resources/cr_elements/cr_icon/cr_icon.js';
import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.js';
import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js';
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
import '/shared/settings/controls/extension_controlled_indicator.js';
import '/shared/settings/prefs/prefs.js';
import '../controls/settings_toggle_button.js';
import '../settings_page/settings_subpage.js';
import '../settings_shared.css.js';
import '../simple_confirmation_dialog.js';
import './credit_card_edit_dialog.js';
import './iban_edit_dialog.js';
import './passwords_shared.css.js';
import './payments_list.js';
import './virtual_card_unenroll_dialog.js';
import './your_saved_info_shared.css.js';
import { AnchorAlignment } from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
import { I18nMixin } from 'chrome://resources/cr_elements/i18n_mixin.js';
import { assert } from 'chrome://resources/js/assert.js';
import { focusWithoutInk } from 'chrome://resources/js/focus_without_ink.js';
import { OpenWindowProxyImpl } from 'chrome://resources/js/open_window_proxy.js';
import { PolymerElement } from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import { loadTimeData } from '../i18n_setup.js';
import { CvcDeletionUserAction, MetricsBrowserProxyImpl, PrivacyElementInteractions } from '../metrics_browser_proxy.js';
import { SettingsViewMixin } from '../settings_page/settings_view_mixin.js';
import { PaymentsManagerImpl } from './payments_manager_proxy.js';
import { getTemplate } from './payments_section.html.js';
const SettingsPaymentsSectionElementBase = SettingsViewMixin(I18nMixin(PolymerElement));
export class SettingsPaymentsSectionElement extends SettingsPaymentsSectionElementBase {
    static get is() {
        return 'settings-payments-section';
    }
    static get template() {
        return getTemplate();
    }
    static get properties() {
        return {
            prefs: Object,
            /**
             * An array of all saved credit cards.
             */
            creditCards: {
                type: Array,
                value: () => [],
            },
            /**
             * An array of all saved IBANs.
             */
            ibans: {
                type: Array,
                value: () => [],
            },
            /**
             * An array of all saved pay over time issuers.
             */
            payOverTimeIssuers: {
                type: Array,
                value: () => [],
            },
            /**
             * Whether IBAN is supported in Settings page.
             */
            showIbanSettingsEnabled_: {
                type: Boolean,
                value() {
                    return loadTimeData.getBoolean('showIbansSettings');
                },
                readOnly: true,
            },
            /**
             * Whether Google Wallet branding should be used instead of Google Pay
             * branding.
             */
            autofillEnableWalletBrandingEnabled_: {
                type: Boolean,
                value() {
                    return loadTimeData.getBoolean('autofillEnableWalletBranding');
                },
                readOnly: true,
            },
            /**
             * The model for any credit card-related action menus or dialogs.
             */
            activeCreditCard_: Object,
            /**
             * The model for any IBAN-related action menus or dialogs.
             */
            activeIban_: Object,
            showCreditCardDialog_: Boolean,
            showIbanDialog_: Boolean,
            showLocalCreditCardRemoveConfirmationDialog_: Boolean,
            showLocalIbanRemoveConfirmationDialog_: Boolean,
            showVirtualCardUnenrollDialog_: Boolean,
            showBulkRemoveCvcConfirmationDialog_: Boolean,
            /**
             * Checks if we can use device authentication to authenticate the user.
             */
            // 
            /**
             * Checks if CVC storage is available based on the feature flag.
             */
            cvcStorageAvailable_: {
                type: Boolean,
                value() {
                    return loadTimeData.getBoolean('cvcStorageAvailable');
                },
            },
            /**
             * Sublabel for the card benefits toggle. The sublabel text also includes
             * a link to learn about the card benefits.
             */
            cardBenefitsSublabel_: {
                type: String,
                value() {
                    return loadTimeData.getString('cardBenefitsToggleSublabel');
                },
            },
            /**
             * Checks if a mandatory reauth feature flag is enabled.
             */
            mandatoryReauthFeatureFlagEnabled_: {
                type: Boolean,
                value() {
                    return loadTimeData.getBoolean('mandatoryReauthFeatureFlagEnabled');
                },
            },
            /**
             * Checks if pay over time should be shown from the settings page.
             */
            shouldShowPayOverTimeSettings_: {
                type: Boolean,
                value() {
                    return loadTimeData.getBoolean('shouldShowPayOverTimeSettings');
                },
                readOnly: true,
            },
            /**
             * Sublabel for the pay over time toggle. The sublabel text also includes
             * a link to learn about pay over time.
             */
            payOverTimeSublabel_: {
                type: String,
                value() {
                    return loadTimeData.getString('autofillPayOverTimeSettingsSublabel');
                },
            },
            /**
             * Indicates if this element is used as a Your saved info subpage. Causes
             * slight adjustments like different title, no page shadow, cards being
             * visible.
             */
            isYourSavedInfoSubpage_: {
                type: Boolean,
                value: () => loadTimeData.getBoolean('enableYourSavedInfoSettingsPage'),
            },
        };
    }
    paymentsManager_ = PaymentsManagerImpl.getInstance();
    setPersonalDataListener_ = null;
    connectedCallback() {
        super.connectedCallback();
        // Create listener function.
        const setCreditCardsListener = (cardList) => {
            this.setCreditCards_(cardList);
        };
        const setPersonalDataListener = (_addressList, cardList, ibanList, payOverTimeIssuerList) => {
            this.setCreditCards_(cardList);
            this.ibans = ibanList;
            if (this.shouldShowPayOverTimeSettings_) {
                this.payOverTimeIssuers = payOverTimeIssuerList;
            }
        };
        const setIbansListener = (ibanList) => {
            this.ibans = ibanList;
        };
        // Remember the bound reference in order to detach.
        this.setPersonalDataListener_ = setPersonalDataListener;
        // Request initial data.
        this.paymentsManager_.getCreditCardList().then(setCreditCardsListener);
        this.paymentsManager_.getIbanList().then(setIbansListener);
        if (this.shouldShowPayOverTimeSettings_) {
            this.paymentsManager_.getPayOverTimeIssuerList().then((issuers) => {
                this.payOverTimeIssuers = issuers;
            });
        }
        // Listen for changes.
        this.paymentsManager_.setPersonalDataManagerListener(setPersonalDataListener);
        // 
        // Record that the user opened the payments settings.
        chrome.metricsPrivate.recordUserAction('AutofillCreditCardsViewed');
        // Measure clicks on the 'Google Account' link for managing payment methods.
        const manageAccountAnchor = this.$.manageLink.querySelector('a');
        if (manageAccountAnchor !== null) {
            manageAccountAnchor.addEventListener('click', () => {
                MetricsBrowserProxyImpl.getInstance().recordAction('Autofill.PaymentMethodsSettingsPage.ManagePaymentMethodsLinkClicked');
            });
        }
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        assert(this.setPersonalDataListener_);
        this.paymentsManager_.removePersonalDataManagerListener(this.setPersonalDataListener_);
        this.setPersonalDataListener_ = null;
    }
    getMultiCardClass_() {
        return this.isYourSavedInfoSubpage_ ? 'multi-card' : '';
    }
    getPageTitleLabel_() {
        return this.i18n(this.isYourSavedInfoSubpage_ ? 'paymentsTitle' : 'creditCards');
    }
    setCreditCards_(cardList) {
        this.creditCards = cardList;
        // To align with Android, only record this histogram when the pref is
        // enabled.
        const autofillEnabledPref = this.get('prefs.autofill.credit_card_enabled');
        if (!!autofillEnabledPref && autofillEnabledPref.value) {
            MetricsBrowserProxyImpl.getInstance().recordBooleanHistogram('Autofill.PaymentMethodsSettingsPage.CardsViewedWithoutExistingCards', this.creditCards.length === 0);
        }
    }
    /**
     * Returns true if IBAN should be shown from settings page.
     * TODO(crbug.com/40234941): Add additional check (starter country-list, or
     * the saved-pref-boolean on if the user has submitted an IBAN form).
     */
    shouldShowIbanSettings_() {
        return this.showIbanSettingsEnabled_;
    }
    /**
     * Opens the dropdown menu to add a credit/debit card or IBAN.
     */
    onAddPaymentMethodClick_(e) {
        const target = e.currentTarget;
        const menu = this.shadowRoot
            .querySelector('#paymentMethodsActionMenu').get();
        assert(menu);
        menu.showAt(target, {
            anchorAlignmentX: AnchorAlignment.BEFORE_END,
            anchorAlignmentY: AnchorAlignment.AFTER_END,
            noOffset: true,
        });
    }
    /**
     * Opens the credit card action menu.
     */
    onCreditCardDotsMenuClick_(e) {
        // Copy item so dialog won't update model on cancel.
        this.activeCreditCard_ = e.detail.creditCard;
        this.$.creditCardSharedMenu.showAt(e.detail.anchorElement);
    }
    /**
     * Opens the IBAN action menu.
     */
    onDotsIbanMenuClick_(e) {
        // Copy item so dialog won't update model on cancel.
        this.activeIban_ = e.detail.iban;
        this.$.ibanSharedActionMenu.get().showAt(e.detail.anchorElement);
    }
    /**
     * Handles clicking on the "Add credit card" button.
     */
    onAddCreditCardClick_(e) {
        e.preventDefault();
        MetricsBrowserProxyImpl.getInstance().recordBooleanHistogram('Autofill.PaymentMethodsSettingsPage.AddCardClicked2', true);
        MetricsBrowserProxyImpl.getInstance().recordBooleanHistogram('Autofill.PaymentMethodsSettingsPage.AddCardClickedWithoutExistingCards2', this.creditCards.length === 0);
        const date = new Date(); // Default to current month/year.
        const expirationMonth = date.getMonth() + 1; // Months are 0 based.
        this.activeCreditCard_ = {
            expirationMonth: expirationMonth.toString(),
            expirationYear: date.getFullYear().toString(),
        };
        this.showCreditCardDialog_ = true;
        if (this.showIbanSettingsEnabled_) {
            const menu = this.shadowRoot
                .querySelector('#paymentMethodsActionMenu').get();
            assert(menu);
            menu.close();
        }
    }
    onCreditCardDialogClose_() {
        this.showCreditCardDialog_ = false;
        this.activeCreditCard_ = null;
    }
    /**
     * Handles clicking on the add "IBAN" option.
     */
    onAddIbanClick_(e) {
        e.preventDefault();
        this.showIbanDialog_ = true;
        const menu = this.shadowRoot
            .querySelector('#paymentMethodsActionMenu').get();
        assert(menu);
        menu.close();
    }
    onIbanDialogClose_() {
        this.showIbanDialog_ = false;
        this.activeIban_ = null;
    }
    /**
     * Handles clicking on the "Edit" credit card button.
     */
    async onMenuEditCreditCardClick_(e) {
        e.preventDefault();
        assert(this.activeCreditCard_);
        if (this.activeCreditCard_.metadata.isLocal) {
            const unmaskedCreditCard = await this.paymentsManager_.getLocalCard(this.activeCreditCard_.guid);
            assert(unmaskedCreditCard);
            this.activeCreditCard_ = unmaskedCreditCard;
            this.showCreditCardDialog_ = true;
        }
        else {
            this.onRemoteCreditCardUrlClick_();
        }
        this.$.creditCardSharedMenu.close();
    }
    onRemoteEditCreditCardClick_(e) {
        this.activeCreditCard_ = e.detail.creditCard;
        this.onRemoteCreditCardUrlClick_();
    }
    onRemoteCreditCardUrlClick_() {
        this.paymentsManager_.logServerCardLinkClicked();
        const url = new URL(loadTimeData.getString('managePaymentMethodsUrl'));
        assert(this.activeCreditCard_);
        if (this.activeCreditCard_.instrumentId) {
            url.searchParams.append('id', this.activeCreditCard_.instrumentId);
        }
        OpenWindowProxyImpl.getInstance().openUrl(url.toString());
    }
    onRemoteEditIbanMenuClick_(e) {
        this.activeIban_ = e.detail.iban;
        this.paymentsManager_.logServerIbanLinkClicked();
        const url = new URL(loadTimeData.getString('managePaymentMethodsUrl'));
        assert(this.activeIban_);
        if (this.activeIban_.instrumentId) {
            url.searchParams.append('id', this.activeIban_.instrumentId);
        }
        OpenWindowProxyImpl.getInstance().openUrl(url.toString());
    }
    onLocalCreditCardRemoveConfirmationDialogClose_() {
        // Only remove the credit card entry if the user closed the dialog via the
        // confirmation button (instead of cancel or close).
        const confirmationDialog = this.shadowRoot.querySelector('#localCardDeleteConfirmDialog');
        assert(confirmationDialog);
        if (confirmationDialog.wasConfirmed()) {
            assert(this.activeCreditCard_);
            assert(this.activeCreditCard_.guid);
            const index = this.creditCards.findIndex((card) => card.guid === this.activeCreditCard_.guid);
            if (!this.$.paymentsList.updateFocusBeforeCreditCardRemoval(index)) {
                this.focusHeaderControls_();
            }
            this.paymentsManager_.removeCreditCard(this.activeCreditCard_.guid);
            this.activeCreditCard_ = null;
        }
        this.showLocalCreditCardRemoveConfirmationDialog_ = false;
    }
    /**
     * Handles clicking on the "Remove" credit card button.
     */
    onMenuRemoveCreditCardClick_() {
        this.showLocalCreditCardRemoveConfirmationDialog_ = true;
        this.$.creditCardSharedMenu.close();
    }
    /**
     * Handles clicking on the "Edit" IBAN button.
     */
    onMenuEditIbanClick_(e) {
        e.preventDefault();
        this.showIbanDialog_ = true;
        this.$.ibanSharedActionMenu.get().close();
    }
    onLocalIbanRemoveConfirmationDialogClose_() {
        // Only remove the IBAN entry if the user closed the dialog via the
        // confirmation button (instead of cancel or close).
        const confirmationDialog = this.shadowRoot.querySelector('#localIbanDeleteConfirmationDialog');
        assert(confirmationDialog);
        if (confirmationDialog.wasConfirmed()) {
            assert(this.activeIban_);
            assert(this.activeIban_.guid);
            const index = this.ibans.findIndex((iban) => iban.guid === this.activeIban_.guid);
            if (!this.$.paymentsList.updateFocusBeforeIbanRemoval(index)) {
                this.focusHeaderControls_();
            }
            this.paymentsManager_.removeIban(this.activeIban_.guid);
            this.activeIban_ = null;
        }
        this.showLocalIbanRemoveConfirmationDialog_ = false;
    }
    /**
     * Handles clicking on the "Remove" IBAN button.
     */
    onMenuRemoveIbanClick_() {
        assert(this.activeIban_);
        this.showLocalIbanRemoveConfirmationDialog_ = true;
        this.$.ibanSharedActionMenu.get().close();
    }
    onMenuAddVirtualCardClick_() {
        this.paymentsManager_.addVirtualCard(this.activeCreditCard_.guid);
        this.$.creditCardSharedMenu.close();
        this.activeCreditCard_ = null;
    }
    onMenuRemoveVirtualCardClick_() {
        this.showVirtualCardUnenrollDialog_ = true;
        this.$.creditCardSharedMenu.close();
    }
    onVirtualCardUnenrollDialogClose_() {
        this.showVirtualCardUnenrollDialog_ = false;
        this.activeCreditCard_ = null;
    }
    /**
     * Records changes made to the "Allow sites to check if you have payment
     * methods saved" setting to a histogram.
     */
    onCanMakePaymentChange_() {
        MetricsBrowserProxyImpl.getInstance().recordSettingsPageHistogram(PrivacyElementInteractions.PAYMENT_METHOD);
    }
    /**
     * Listens for the save-credit-card event, and calls the private API.
     */
    saveCreditCard_(event) {
        this.paymentsManager_.saveCreditCard(event.detail);
    }
    onSaveIban_(event) {
        this.paymentsManager_.saveIban(event.detail);
    }
    getMenuEditCardText_(isLocalCard) {
        if (isLocalCard) {
            return this.i18n('edit');
        }
        return this.i18n(this.autofillEnableWalletBrandingEnabled_ ? 'editServerCardInWallet' :
            'editServerCard');
    }
    shouldShowAddVirtualCardButton_() {
        if (this.activeCreditCard_ === null || !this.activeCreditCard_.metadata) {
            return false;
        }
        return !!this.activeCreditCard_.metadata.isVirtualCardEnrollmentEligible &&
            !this.activeCreditCard_.metadata.isVirtualCardEnrolled;
    }
    shouldShowRemoveVirtualCardButton_() {
        if (this.activeCreditCard_ === null || !this.activeCreditCard_.metadata) {
            return false;
        }
        return !!this.activeCreditCard_.metadata.isVirtualCardEnrollmentEligible &&
            !!this.activeCreditCard_.metadata.isVirtualCardEnrolled;
    }
    /**
     * Listens for the unenroll-virtual-card event, and calls the private API.
     */
    unenrollVirtualCard_(event) {
        this.paymentsManager_.removeVirtualCard(event.detail);
    }
    // 
    focusHeaderControls_() {
        const element = this.shadowRoot.querySelector('.header-aligned-button');
        if (element) {
            focusWithoutInk(element);
        }
    }
    /**
     * Checks for user auth before flipping the mandatory auth toggle.
     */
    onMandatoryAuthToggleChange_(e) {
        const mandatoryAuthToggle = e.target;
        assert(mandatoryAuthToggle);
        // The toggle is reset to the value when it was clicked.
        // It will be flipped afterwards if the user auth is successful.
        mandatoryAuthToggle.checked = !mandatoryAuthToggle.checked;
        this.paymentsManager_.authenticateUserAndFlipMandatoryAuthToggle();
    }
    /**
     * Method to handle the clicking of bulk delete all the CVCs.
     */
    onBulkRemoveCvcClick_() {
        assert(this.cvcStorageAvailable_);
        // Log the metric for user clicking on the bulk delete hyperlink which
        // triggers the dialog window.
        MetricsBrowserProxyImpl.getInstance().recordAction(CvcDeletionUserAction.HYPERLINK_CLICKED);
        this.showBulkRemoveCvcConfirmationDialog_ = true;
    }
    /**
     * Method to bulk delete all the CVCs present on the local DB.
     */
    onShowBulkRemoveCvcConfirmationDialogClose_() {
        assert(this.cvcStorageAvailable_);
        const confirmationDialog = this.shadowRoot.querySelector('#bulkDeleteCvcConfirmDialog');
        assert(confirmationDialog);
        // Log the metric for user either clicking on "Delete" or "Cancel" on the
        // bulk delete dialog window.
        MetricsBrowserProxyImpl.getInstance().recordAction(confirmationDialog.wasConfirmed() ?
            CvcDeletionUserAction.DIALOG_ACCEPTED :
            CvcDeletionUserAction.DIALOG_CANCELLED);
        if (confirmationDialog.wasConfirmed()) {
            this.paymentsManager_.bulkDeleteAllCvcs();
        }
        this.showBulkRemoveCvcConfirmationDialog_ = false;
        // Focus on the CVC storage toggle, post deletion of CVCs for voice reader
        // correctness.
        const cvcStorageToggle = this.shadowRoot.querySelector('#cvcStorageToggle');
        assert(cvcStorageToggle);
        cvcStorageToggle.focus();
    }
    /**
     * Method to return the correct sublabel for the cvc storage toggle.
     * If any card from the list has a cvc, the sublabel with bulk delete
     * hyperlink is returned else return the regular sublabel.
     * @returns Cvc storage toggle sublabel string.
     */
    getCvcStorageSublabel_() {
        const card = this.creditCards.find(cc => !!cc.cvc);
        return loadTimeData.getStringF(card === undefined ? 'enableCvcStorageSublabel' :
            'enableCvcStorageDeleteDataSublabel');
    }
    /**
     * Opens an article to learn about card benefits when the card benefits toggle
     * sublabel link is clicked.
     */
    onCardBenefitsSublabelLinkClick_() {
        OpenWindowProxyImpl.getInstance().openUrl(loadTimeData.getString('cardBenefitsToggleLearnMoreUrl'));
    }
    /**
     * Get the CVC storage toggle aria label for a11y voice readers.
     * @returns CVC storage aria label.
     */
    getCvcStorageAriaLabel_() {
        const card = this.creditCards.find(cc => !!cc.cvc);
        return this.i18n(card === undefined ? 'enableCvcStorageAriaLabelForNoCvcSaved' :
            'enableCvcStorageLabel');
    }
    /**
     * Get the body text for the CVC deletion dialog, depending on whether Google
     * Wallet branding is enabled or not.
     */
    getCvcDeletionDialogBodyText_() {
        return this.i18n(this.autofillEnableWalletBrandingEnabled_ ?
            'bulkRemoveCvcFromWalletConfirmationDescription' :
            'bulkRemoveCvcConfirmationDescription');
    }
    /**
     * Opens an article to learn about pay over time when the pay over time
     * toggle sublabel link is clicked.
     */
    onPayOverTimeSublabelLinkClick_() {
        OpenWindowProxyImpl.getInstance().openUrl(loadTimeData.getString('autofillPayOverTimeSettingsLearnMoreUrl'));
    }
    // SettingsViewMixin implementation.
    focusBackButton() {
        this.shadowRoot.querySelector('settings-subpage').focusBackButton();
    }
}
customElements.define(SettingsPaymentsSectionElement.is, SettingsPaymentsSectionElement);
