import { useAccountPayeeBankDetailsQuery } from 'src/apollo/queries/account-payee-bank-details';
import {
    ABACUS_ACTION_STATUSES,
    ABACUS_ACTIONS,
    EMPTY_CHAR,
    PAYEE_TYPES,
} from '@theorchard/accounting-apps-shared';
import { Page } from '@theorchard/suite-frontend';
import { Label, Section, SkeletonLoader } from '@theorchard/suite-components';
import { AccountPayoutMethod } from 'src/components/account-detail/account-payout-method';
import { AccountManagement } from 'src/components/payment-details-review/components/account-management';
import React, { useEffect, useState } from 'react';
import { GlyphIcon } from '@theorchard/suite-icons';
import { AbacusAccount } from 'src/components/payment-details-review/components/payment-details-body';
import type { CountryCode } from 'libphonenumber-js';
import { MaskedValue } from 'src/components/shared/masked-value';

// Cache the dynamically-loaded module promise so concurrent <PhoneNumber />
// instances (and re-renders) share a single network/parse trip.
let phoneLibPromise: Promise<typeof import('libphonenumber-js')> | null = null;
const loadPhoneLib = () => {
    if (!phoneLibPromise) {
        phoneLibPromise = import(
            /* webpackChunkName: "libphonenumber-js" */ 'libphonenumber-js'
        );
    }
    return phoneLibPromise;
};

type BankDetails = NonNullable<
    NonNullable<NonNullable<AbacusAccount['accountPayee']>['bankDetails']>
>;

type Contact = NonNullable<NonNullable<BankDetails>['contact']>;

interface PaymentDetailGridProps {
    accountId: string;
}

interface PhoneNumberProps {
    phone?: Contact['phone'];
    phoneCountry?: Contact['phoneCountry'];
}

const PhoneNumber: React.FC<PhoneNumberProps> = ({ phone, phoneCountry }) => {
    // Default to EMPTY_CHAR when no phone is set; otherwise fall back to the
    // raw phone string while libphonenumber-js loads, so the rare slow-network
    // case still shows *something* instead of blank.
    const [parsedPhone, setParsedPhone] = useState<string>(() =>
        phone && phoneCountry ? phone : EMPTY_CHAR
    );

    useEffect(() => {
        if (!phone || !phoneCountry) {
            setParsedPhone(EMPTY_CHAR);
            return;
        }

        let cancelled = false;
        loadPhoneLib()
            .then(({ default: parsePhoneNumberFromString }) => {
                if (cancelled) return;
                try {
                    const parsed = parsePhoneNumberFromString(
                        phone,
                        phoneCountry as CountryCode
                    );
                    setParsedPhone(
                        parsed ? parsed.formatInternational() : phone
                    );
                } catch {
                    setParsedPhone(phone);
                }
            })
            .catch(() => {
                if (!cancelled) setParsedPhone(phone);
            });

        return () => {
            cancelled = true;
        };
    }, [phone, phoneCountry]);

    return (
        <Page.Col sm={12} md={3}>
            <Label text="Phone Number" />
            {parsedPhone === EMPTY_CHAR ? (
                EMPTY_CHAR
            ) : (
                <MaskedValue value={parsedPhone} />
            )}
        </Page.Col>
    );
};

const PaymentDetailGrid: React.FC<PaymentDetailGridProps> = ({ accountId }) => {
    const {
        data: accountBankDetails,
        loading: accountPayeeBankDetailsQueryLoading,
    } = useAccountPayeeBankDetailsQuery(accountId);

    const accountDetails = accountBankDetails?.abacusAccount;
    const bankDetails = accountDetails?.accountPayee?.bankDetails;
    const bankDetailsType = bankDetails?.type;

    const paymentEligibility = accountDetails?.accountPayee?.actionStates?.find(
        (item: { actionName: string }) =>
            item.actionName === ABACUS_ACTIONS.PAYMENT_ELIGIBILITY
    );
    const isApproved =
        paymentEligibility?.actionStatus === ABACUS_ACTION_STATUSES.APPROVED;

    const paymentDetails = (
        <>
            <Page.Grid>
                {bankDetailsType === PAYEE_TYPES.INDIVIDUAL ? (
                    <>
                        <Page.Col sm={12} md={3}>
                            <Label text="First name" />
                            {bankDetails?.contact?.firstName || EMPTY_CHAR}
                        </Page.Col>
                        <Page.Col sm={12} md={3}>
                            <Label text="Last Name" />
                            {bankDetails?.contact?.lastName || EMPTY_CHAR}
                        </Page.Col>
                    </>
                ) : (
                    <Page.Col sm={12} md={3}>
                        <div className="column-item">
                            <Label text="Company Name" />
                            {bankDetails?.company?.name || EMPTY_CHAR}
                        </div>
                    </Page.Col>
                )}
                <AccountPayoutMethod accountDetails={accountDetails} />
                <AccountManagement accountId={accountId} withContactData />
                <Page.Col sm={12} md={3}>
                    <div className="column-item">
                        <Label text="Email" />
                        {bankDetails?.contact?.email || EMPTY_CHAR}
                    </div>
                </Page.Col>
                <PhoneNumber
                    phone={bankDetails?.contact?.phone}
                    phoneCountry={bankDetails?.contact?.phoneCountry}
                />
            </Page.Grid>
            {isApproved && (
                <>
                    <Section.Divider />
                    <div className="glyphWithLabel">
                        <GlyphIcon name="flag" size={16} />
                        <Label text="Approval notes" />
                    </div>
                    {paymentEligibility?.message || EMPTY_CHAR}
                </>
            )}
        </>
    );

    return accountPayeeBankDetailsQueryLoading ? (
        <SkeletonLoader numberOfItems={4} vertical />
    ) : (
        paymentDetails
    );
};

export default PaymentDetailGrid;
