import type { FC } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import { BRAND_AWAL } from '@theorchard/constants';
import { useAppConfig } from '@theorchard/suite-config';
import { formatMessage, getCurrentLocale } from '@theorchard/suite-i18n';
import { NavIcon } from '@theorchard/suite-icons';
import { useIdentity } from '@theorchard/suite-identity';
import { useTheme, themes, rgbToHex } from '@theorchard/suite-theming';
import { SuiteLogger } from '@theorchard/suite-utils';
import cx from 'classnames';
import { useAppContext } from '../../app/appContext';
import { EVENT_HELP_CLICKED } from '../../constants/events';
import { getZendeskAuthCallback } from '../../queries/zendeskToken';
import Segment from '../../segment';
import { getBrandExperienceFromBrand } from '../../utils/brandExperience';

const CLASSNAME = 'ZendeskButton';
const TERM_HELP = 'navigation_help';
const SCRIPT_ID = 'ze-snippet';

export interface Props {
    asNavLink?: boolean;
}

export const ZendeskButton: FC<Props> = ({ asNavLink = false }) => {
    const user = useIdentity();
    const { zendeskKey, zendeskTicketFormIds, brand, appName } = useAppConfig();
    const { graphqlClient } = useAppContext();
    const { theme } = useTheme();
    const { colors: themeColors } = themes[theme];
    const [isWidgetLoaded, setIsWidgetLoaded] = useState(false);

    const widgetColors = useMemo(
        () => ({
            button: rgbToHex(themeColors['midnight-650']),
            resultLists: rgbToHex(themeColors['midnight-450']),
            header: rgbToHex(themeColors['midnight-850']),
            articleLinks: rgbToHex(themeColors['midnight-850']),
        }),
        [themeColors]
    );

    useEffect(() => {
        if (!zendeskKey) {
            SuiteLogger.debug(
                'Zendesk',
                'No "zendeskKey" has been defined in the app configuration.'
            );
            return;
        }

        const onLoad = () => {
            SuiteLogger.info('Zendesk', 'widget loaded');
            window.zE?.('webWidget', 'hide');
            setIsWidgetLoaded(true);
            document.getElementById(SCRIPT_ID)?.setAttribute('data-loaded', '');
        };

        const existingScript = document.getElementById(SCRIPT_ID);
        if (existingScript) {
            if (existingScript.hasAttribute('data-loaded')) {
                onLoad();
                return;
            } else {
                existingScript.addEventListener('load', onLoad);
                return () => existingScript.removeEventListener('load', onLoad);
            }
        }

        window.zESettings = {
            webWidget: {
                offset: { horizontal: '230px', vertical: '50px' },
                position: { horizontal: 'left' },
            },
        };

        const script = document.createElement('script');
        script.id = SCRIPT_ID;
        script.setAttribute('data-testid', 'ZendeskScript');
        script.src = `https://static.zdassets.com/ekr/snippet.js?key=${zendeskKey}`;
        script.async = true;
        script.addEventListener('load', onLoad);
        document.body.appendChild(script);

        return () => script.removeEventListener('load', onLoad);
    }, [zendeskKey]);

    useEffect(() => {
        // We need to wait until zendesk widget is fully loaded before update its settings
        // Updating webWidget.authenticate before load have no effect
        if (!isWidgetLoaded) return;

        window.zE?.('webWidget', 'identify', {
            name: user.name,
            email: user.email,
            organization: user.defaultBrand,
        });

        let contactFormConfig;
        if (zendeskTicketFormIds) {
            contactFormConfig = {
                ticketForms: zendeskTicketFormIds.split(/\s*,\s*/).map((id) => ({ id })),
            };
        } else {
            contactFormConfig = {
                fields: [{ id: 'email', prefill: { '*': user.email } }],
            };
        }

        window.zE?.('webWidget', 'updateSettings', {
            webWidget: {
                contactForm: contactFormConfig,
            },
        });

        if (brand === BRAND_AWAL) {
            const brandExperience = getBrandExperienceFromBrand(brand);
            window.zE?.('webWidget', 'updateSettings', {
                webWidget: {
                    authenticate: {
                        jwtFn: getZendeskAuthCallback(graphqlClient, user.id, brandExperience),
                    },
                },
            });
        }

        window.zE?.('webWidget', 'setLocale', getCurrentLocale());
    }, [brand, graphqlClient, user, isWidgetLoaded, zendeskTicketFormIds]);

    return (
        <button
            type="button"
            id="zendeskButton"
            className={cx(CLASSNAME, { NavLink: asNavLink })}
            data-testid={CLASSNAME}
            onClick={() => {
                window.zE?.('webWidget:on', 'open', () => {
                    void Segment.trackEvent(EVENT_HELP_CLICKED);
                });
                window.zE?.('webWidget', 'show');
                window.zE?.('webWidget', 'toggle');
                window.zE?.('webWidget:on', 'close', () => {
                    window.zE?.('webWidget', 'hide');
                });
                window.zE?.('webWidget', 'updateSettings', {
                    webWidget: {
                        color: widgetColors,
                    },
                });

                if (brand === BRAND_AWAL && appName) {
                    window.zE?.('webWidget', 'updateSettings', {
                        webWidget: {
                            answerBot: {
                                suppress: true,
                            },
                        },
                    });
                    window.zE?.('webWidget', 'helpCenter:setSuggestions', {
                        search: appName.replace('frontend-', ''),
                    });
                }
            }}
        >
            {asNavLink ? (
                <>
                    <div className="NavLink-icon">
                        <NavIcon name="HelpNavIcon" />
                    </div>
                    <span className="NavLink-title">{formatMessage(TERM_HELP)}</span>
                </>
            ) : (
                <>
                    <NavIcon name="HelpNavIcon" />
                    {formatMessage(TERM_HELP)}
                </>
            )}
        </button>
    );
};
