import { ReactNode, useMemo } from 'react';
import { useTranslation } from 'react-i18next';

import styles from './list-config-menu.module.css';

import i18n from '/@/i18n/i18n';
import { GridConfig } from '/@/renderer/features/shared/components/grid-config';
import { SettingsButton } from '/@/renderer/features/shared/components/settings-button';
import { TableConfig } from '/@/renderer/features/shared/components/table-config';
import { useSettingsStore, useSettingsStoreActions } from '/@/renderer/store';
import { ActionIconProps } from '/@/shared/components/action-icon/action-icon';
import { Divider } from '/@/shared/components/divider/divider';
import { Group } from '/@/shared/components/group/group';
import { Icon } from '/@/shared/components/icon/icon';
import { Modal } from '/@/shared/components/modal/modal';
import { SegmentedControl } from '/@/shared/components/segmented-control/segmented-control';
import { Stack } from '/@/shared/components/stack/stack';
import { Switch } from '/@/shared/components/switch/switch';
import { Table } from '/@/shared/components/table/table';
import { Text } from '/@/shared/components/text/text';
import { useDisclosure } from '/@/shared/hooks/use-disclosure';
import { ItemListKey, ListDisplayType } from '/@/shared/types/types';

export const SONG_DISPLAY_TYPES: ListConfigMenuDisplayTypeConfig[] = [
    { hidden: true, value: ListDisplayType.DETAIL },
];

const DISPLAY_TYPES = [
    {
        label: (
            <Group align="center" gap="sm" justify="center" p="sm" wrap="nowrap">
                <Icon icon="layoutTable" size="lg" />
                {i18n.t('table.config.view.table') as string}
            </Group>
        ),
        value: ListDisplayType.TABLE,
    },
    {
        label: (
            <Group align="center" gap="sm" justify="center" p="sm" wrap="nowrap">
                <Icon icon="layoutGrid" size="lg" />
                {i18n.t('table.config.view.grid') as string}
            </Group>
        ),
        value: ListDisplayType.GRID,
    },
    {
        label: (
            <Group align="center" gap="sm" justify="center" p="sm" wrap="nowrap">
                <Icon icon="layoutDetail" size="lg" />
                {i18n.t('table.config.view.detail') as string}
            </Group>
        ),
        value: ListDisplayType.DETAIL,
    },
    // {
    //     disabled: true,
    //     label: (
    //         <Stack align="center" p="sm">
    //             <Icon icon="layoutList" size="lg" />
    //             {i18n.t('table.config.view.list') as string}
    //         </Stack>
    //     ),
    //     value: ListDisplayType.LIST,
    // },
];

export const ListConfigBooleanControl = ({
    onChange,
    value,
}: {
    onChange: (value: boolean) => void;
    value: boolean;
}) => {
    return (
        <Group justify="flex-end" w="100%">
            <Switch checked={value} onChange={(e) => onChange(e.currentTarget.checked)} />
        </Group>
    );
};

export interface ListConfigMenuDetailConfig {
    optionsConfig?: ListConfigMenuOptionsConfig['detail'];
    tableColumnsData: { label: string; value: string }[];
    tableKey: 'detail';
}

export interface ListConfigMenuDisplayTypeConfig {
    disabled?: boolean;
    hidden?: boolean;
    value: ListDisplayType;
}

export interface ListConfigMenuOptionConfig {
    disabled?: boolean;
    hidden?: boolean;
}

export interface ListConfigMenuOptionsConfig {
    detail?: {
        [key: string]: ListConfigMenuOptionConfig;
    };
    grid?: {
        [key: string]: ListConfigMenuOptionConfig;
    };
    table?: {
        [key: string]: ListConfigMenuOptionConfig;
    };
}

interface ListConfigMenuProps {
    buttonProps?: ActionIconProps;
    detailConfig?: ListConfigMenuDetailConfig;
    displayTypes?: ListConfigMenuDisplayTypeConfig[];
    listKey: ItemListKey;
    optionsConfig?: ListConfigMenuOptionsConfig;
    tableColumnsData: { label: string; value: string }[];
}

export const ListConfigMenu = (props: ListConfigMenuProps) => {
    const { t } = useTranslation();
    const displayType = useSettingsStore(
        (state) => state.lists[props.listKey]?.display,
    ) as ListDisplayType;
    const { setList } = useSettingsStoreActions();
    const [isOpen, handlers] = useDisclosure(false);

    // Filter display types based on config
    const availableDisplayTypes = useMemo(() => {
        if (!props.displayTypes) {
            return DISPLAY_TYPES;
        }

        const filtered = DISPLAY_TYPES.map((type) => {
            const config = props.displayTypes?.find((c) => c.value === type.value);
            if (config?.hidden) {
                return null;
            }
            const result: (typeof DISPLAY_TYPES)[0] & { disabled?: boolean } = {
                ...type,
            };
            if (config?.disabled) {
                result.disabled = true;
            }
            return result;
        }).filter((type): type is NonNullable<typeof type> => type !== null);

        return filtered;
    }, [props.displayTypes]);

    return (
        <>
            <SettingsButton {...props.buttonProps} onClick={handlers.toggle} />
            <Modal handlers={handlers} opened={isOpen} size="xl" title={t('common.configure')}>
                <Stack gap="xs">
                    {availableDisplayTypes.length > 1 && (
                        <ListConfigTable
                            options={[
                                {
                                    component: (
                                        <SegmentedControl
                                            data={availableDisplayTypes}
                                            fullWidth
                                            onChange={(value) => {
                                                setList(props.listKey, {
                                                    display: value as ListDisplayType,
                                                });
                                            }}
                                            size="sm"
                                            value={displayType}
                                            withItemsBorders={false}
                                        />
                                    ),
                                    id: 'displayType',
                                    label: t('table.config.general.displayType'),
                                },
                            ]}
                        />
                    )}
                    <Config displayType={displayType} {...props} />
                </Stack>
            </Modal>
        </>
    );
};

const Config = ({
    displayType,
    optionsConfig,
    tableColumnsData,
    ...props
}: ListConfigMenuProps & { displayType: ListDisplayType }) => {
    switch (displayType) {
        case ListDisplayType.DETAIL:
            if (props.detailConfig) {
                return (
                    <TableConfig
                        enablePinColumnButtons={false}
                        listKey={props.listKey}
                        optionsConfig={props.detailConfig.optionsConfig}
                        tableColumnsData={props.detailConfig.tableColumnsData}
                        tableKey="detail"
                    />
                );
            }
            return null;

        case ListDisplayType.GRID:
            return (
                <GridConfig
                    {...props}
                    gridRowsData={tableColumnsData}
                    optionsConfig={optionsConfig?.grid}
                />
            );

        case ListDisplayType.TABLE:
            return (
                <TableConfig
                    {...props}
                    optionsConfig={optionsConfig?.table}
                    tableColumnsData={tableColumnsData}
                />
            );

        default:
            return null;
    }
};

export const ListConfigTable = ({
    options,
}: {
    options: {
        component: ReactNode;
        description?: ReactNode | string;
        id: string;
        isDivider?: boolean;
        isHidden?: boolean;
        label: ReactNode | string;
    }[];
}) => {
    return (
        <Table
            className={styles.table}
            classNames={{
                td: styles.td,
                th: styles.th,
            }}
            onClick={(e) => e.stopPropagation()}
            variant="vertical"
            withColumnBorders={false}
            withRowBorders={false}
            withTableBorder={false}
        >
            <Table.Tbody>
                {options.map((option) => {
                    if (option.isHidden) {
                        return null;
                    }

                    if (option.isDivider) {
                        return (
                            <Table.Tr key={option.id}>
                                <Table.Td className={styles.dividerCell} colSpan={2}>
                                    <Divider />
                                </Table.Td>
                            </Table.Tr>
                        );
                    }

                    return (
                        <Table.Tr key={option.id}>
                            <Table.Th>
                                {option.description !== undefined ? (
                                    <Stack gap="xs">
                                        <Text isNoSelect size="sm">
                                            {option.label}
                                        </Text>
                                        <Text isMuted isNoSelect size="xs">
                                            {option.description}
                                        </Text>
                                    </Stack>
                                ) : (
                                    option.label
                                )}
                            </Table.Th>
                            <Table.Td>
                                <div className={styles.control}>{option.component}</div>
                            </Table.Td>
                        </Table.Tr>
                    );
                })}
            </Table.Tbody>
        </Table>
    );
};
