import isElectron from 'is-electron';
import { Fragment, ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
import { Link, useNavigate } from 'react-router';

import styles from './app-menu.module.css';

import { UpdateAvailableButton } from '/@/renderer/features/settings/components/update-available-button';
import { openSettingsModal } from '/@/renderer/features/settings/utils/open-settings-modal';
import { ServerSelector } from '/@/renderer/features/sidebar/components/server-selector';
import { openReleaseNotesModal } from '/@/renderer/release-notes-modal';
import {
    useAppStore,
    useAppStoreActions,
    useCommandPalette,
    useCurrentServer,
    useGeneralSettings,
    useLatestVersion,
    useSettingsStoreActions,
} from '/@/renderer/store';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { DropdownMenu, MenuItemProps } from '/@/shared/components/dropdown-menu/dropdown-menu';
import { Flex } from '/@/shared/components/flex/flex';
import { Group } from '/@/shared/components/group/group';
import { Icon } from '/@/shared/components/icon/icon';
import { toast } from '/@/shared/components/toast/toast';

const browser = isElectron() ? window.api.browser : null;

interface BaseMenuItem {
    id: string;
    type: 'conditional-group' | 'conditional-item' | 'custom' | 'divider' | 'item';
}

interface ConditionalGroupItem extends BaseMenuItem {
    condition: boolean;
    items: MenuItem[];
    type: 'conditional-group';
}

interface ConditionalItem extends BaseMenuItem {
    condition: boolean;
    item: Omit<MenuItem, 'id' | 'type'>;
    type: 'conditional-item';
}

interface CustomItem extends BaseMenuItem {
    component: ReactNode;
    type: 'custom';
}

interface DividerItem extends BaseMenuItem {
    type: 'divider';
}

type MenuItem = ConditionalGroupItem | ConditionalItem | CustomItem | DividerItem | RegularMenuItem;

interface RegularMenuItem extends BaseMenuItem {
    component?: 'a' | typeof Link;
    href?: string;
    icon?: keyof typeof import('/@/shared/components/icon/icon').AppIcon;
    iconColor?:
        | 'contrast'
        | 'default'
        | 'error'
        | 'info'
        | 'inherit'
        | 'muted'
        | 'primary'
        | 'success'
        | 'warn';
    label: string;
    leftSection?: ReactNode;
    onClick?: () => void;
    rightSection?: ReactNode;
    target?: string;
    to?: string;
    type: 'item';
}

export const AppMenu = () => {
    const { t } = useTranslation();
    const navigate = useNavigate();
    const collapsed = useAppStore((state) => state.sidebar.collapsed);
    const privateMode = useAppStore((state) => state.privateMode);
    const { setPrivateMode, setSideBar } = useAppStoreActions();
    const { setSettings } = useSettingsStoreActions();
    const settings = useGeneralSettings();
    const currentServer = useCurrentServer();
    const { open: openCommandPalette } = useCommandPalette();

    const handleBrowserDevTools = () => {
        browser?.devtools();
    };

    const handleCollapseSidebar = () => {
        setSideBar({ collapsed: true });
    };

    const handleExpandSidebar = () => {
        setSideBar({ collapsed: false });
    };

    const handlePrivateModeOff = () => {
        setPrivateMode(false);
        toast.info({
            message: t('form.privateMode.disabled'),
            title: t('form.privateMode.title'),
        });
    };

    const handlePrivateModeOn = () => {
        setPrivateMode(true);
        toast.info({
            message: t('form.privateMode.enabled'),
            title: t('form.privateMode.title'),
        });
    };

    const handleQuit = () => {
        browser?.quit();
    };

    const handleSetSideQueueLayout = (sideQueueLayout: 'horizontal' | 'vertical') => {
        setSettings({
            general: {
                ...settings,
                sideQueueLayout,
            },
        });
    };

    const { currentVersion } = useLatestVersion();

    const serverHeaderMenuItems: MenuItem[] = currentServer
        ? [
              {
                  component: (
                      <div className={styles.serverSelector}>
                          <ServerSelector />
                      </div>
                  ),
                  id: 'server-selector',
                  type: 'custom',
              },
              {
                  id: 'divider-server',
                  type: 'divider',
              },
          ]
        : [];

    const menuConfig: MenuItem[] = [
        ...serverHeaderMenuItems,
        {
            icon: 'search',
            id: 'command-palette',
            label: t('page.appMenu.commandPalette'),
            onClick: openCommandPalette,
            type: 'item',
        },
        {
            id: 'divider-1',
            type: 'divider',
        },
        {
            condition: collapsed,
            id: 'navigation-group',
            items: [
                {
                    icon: 'arrowLeftS',
                    id: 'go-back',
                    label: t('page.appMenu.goBack'),
                    onClick: () => navigate(-1),
                    type: 'item',
                },
                {
                    icon: 'arrowRightS',
                    id: 'go-forward',
                    label: t('page.appMenu.goForward'),
                    onClick: () => navigate(1),
                    type: 'item',
                },
            ],
            type: 'conditional-group',
        },
        {
            condition: collapsed,
            id: 'sidebar-expand',
            item: {
                icon: 'panelRightOpen',
                id: 'expand-sidebar',
                label: t('page.appMenu.expandSidebar'),
                onClick: handleExpandSidebar,
                type: 'item',
            },
            type: 'conditional-item',
        },
        {
            condition: !collapsed,
            id: 'sidebar-collapse',
            item: {
                icon: 'panelRightClose',
                id: 'collapse-sidebar',
                label: t('page.appMenu.collapseSidebar'),
                onClick: handleCollapseSidebar,
                type: 'item',
            },
            type: 'conditional-item',
        },
        {
            id: 'divider-2',
            type: 'divider',
        },
        {
            icon: 'settings',
            id: 'settings',
            label: t('page.appMenu.settings'),
            onClick: () => openSettingsModal(),
            type: 'item',
        },
        {
            condition: privateMode,
            id: 'private-mode-off',
            item: {
                icon: 'lock',
                iconColor: 'error',
                label: t('page.appMenu.privateModeOff'),
                onClick: handlePrivateModeOff,
                type: 'item',
            },
            type: 'conditional-item',
        },
        {
            condition: !privateMode,
            id: 'private-mode-on',
            item: {
                icon: 'lockOpen',
                label: t('page.appMenu.privateModeOn'),
                onClick: handlePrivateModeOn,
                type: 'item',
            },
            type: 'conditional-item',
        },
        {
            id: 'divider-4',
            type: 'divider',
        },
        {
            icon: 'brandGitHub',
            id: 'version',
            label: t('page.appMenu.version', { version: currentVersion }),
            onClick: () =>
                openReleaseNotesModal(
                    t('common.newVersion', { version: currentVersion }) as string,
                ),
            type: 'item',
        },
        {
            condition: isElectron(),
            id: 'devtools',
            item: {
                icon: 'appWindow',
                id: 'open-devtools',
                label: t('page.appMenu.openBrowserDevtools'),
                onClick: handleBrowserDevTools,
                type: 'item',
            },
            type: 'conditional-item',
        },
        {
            condition: isElectron(),
            id: 'quit',
            item: {
                icon: 'x',
                id: 'quit-app',
                label: t('page.appMenu.quit'),
                onClick: handleQuit,
                type: 'item',
            },
            type: 'conditional-item',
        },
        {
            component: (
                <Flex align="center" justify="center" w="100%">
                    <UpdateAvailableButton />
                </Flex>
            ),
            id: 'update-available',
            type: 'custom',
        },
        {
            id: 'divider-5',
            type: 'divider',
        },
        {
            condition: settings.sideQueueType === 'sideQueue',
            id: 'layout-toggle-group',
            items: [
                {
                    component: (
                        <Group gap="xs" grow pb="xs" pt="sm" px="xs" w="100%">
                            <ActionIcon
                                icon="layoutPanelRight"
                                iconProps={{
                                    size: 'xl',
                                }}
                                onClick={() => handleSetSideQueueLayout('horizontal')}
                                tooltip={{
                                    label: t('setting.sidePlayQueueLayout', {
                                        context: 'optionHorizontal',
                                    }),
                                    openDelay: 0,
                                    position: 'bottom',
                                }}
                                variant={
                                    settings.sideQueueLayout === 'horizontal'
                                        ? 'default'
                                        : 'transparent'
                                }
                            />
                            <ActionIcon
                                icon="layoutPanelBottom"
                                iconProps={{
                                    size: 'xl',
                                }}
                                onClick={() => handleSetSideQueueLayout('vertical')}
                                tooltip={{
                                    label: t('setting.sidePlayQueueLayout', {
                                        context: 'optionVertical',
                                    }),
                                    openDelay: 0,
                                    position: 'bottom',
                                }}
                                variant={
                                    settings.sideQueueLayout === 'vertical'
                                        ? 'default'
                                        : 'transparent'
                                }
                            />
                        </Group>
                    ),
                    id: 'layout-toggle',
                    type: 'custom',
                },
            ],
            type: 'conditional-group',
        },
    ];

    const renderMenuItem = (item: MenuItem): ReactNode => {
        switch (item.type) {
            case 'conditional-group':
                if (!item.condition) return null;
                return (
                    <div key={item.id}>
                        {item.items.map((subItem) => {
                            return <Fragment key={subItem.id}>{renderMenuItem(subItem)}</Fragment>;
                        })}
                    </div>
                );

            case 'conditional-item':
                if (!item.condition) return null;
                return <Fragment key={item.id}>{renderMenuItem(item.item as MenuItem)}</Fragment>;

            case 'custom':
                return <div key={item.id}>{item.component}</div>;

            case 'divider':
                return <DropdownMenu.Divider key={item.id} />;

            case 'item': {
                const leftSection =
                    item.leftSection ||
                    (item.icon && <Icon color={item.iconColor} icon={item.icon} />);

                const props = {
                    leftSection,
                    ...(item.rightSection && { rightSection: item.rightSection }),
                    ...(item.onClick && { onClick: item.onClick }),
                    ...(item.component && { component: item.component }),
                    ...(item.to && { to: item.to }),
                    ...(item.href && { href: item.href }),
                    ...(item.target && { target: item.target }),
                } as MenuItemProps;

                return (
                    <DropdownMenu.Item key={item.id} {...props}>
                        {item.label}
                    </DropdownMenu.Item>
                );
            }

            default:
                return null;
        }
    };

    return <>{menuConfig.map((item) => renderMenuItem(item))}</>;
};
