import { useCallback, useEffect, useMemo, useState, type VFC } from 'react';
import {
    Box,
    Button,
    IconButton,
    Link,
    Tooltip,
    useMediaQuery,
    useTheme,
} from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { createColumnHelper, useReactTable } from '@tanstack/react-table';
import { PaginatedTable, TablePlaceholder } from 'component/common/Table';
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
import { DateCell } from 'component/common/Table/cells/DateCell/DateCell';
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
import { FeatureTypeCell } from 'component/common/Table/cells/FeatureTypeCell/FeatureTypeCell';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import type { FeatureSchema, FeatureSearchResponseSchema } from 'openapi';
import { FeatureStaleCell } from './FeatureStaleCell/FeatureStaleCell';
import { Search } from 'component/common/Search/Search';
import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi';
import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell';
import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/FavoriteIconHeader';
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
import { ExportDialog } from './ExportDialog';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { focusable } from 'themes/themeStyles';
import { FeatureEnvironmentSeenCell } from 'component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell';
import useToast from 'hooks/useToast';
import { FeatureToggleFilters } from './FeatureToggleFilters/FeatureToggleFilters';
import {
    DEFAULT_PAGE_LIMIT,
    useFeatureSearch,
} from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
import mapValues from 'lodash.mapvalues';
import {
    BooleansStringParam,
    FilterItemParam,
} from 'utils/serializeQueryParams';
import {
    encodeQueryParams,
    NumberParam,
    StringParam,
    withDefault,
} from 'use-query-params';
import { withTableState } from 'utils/withTableState';
import { usePersistentTableState } from 'hooks/usePersistentTableState';
import { FeatureTagCell } from 'component/common/Table/cells/FeatureTagCell/FeatureTagCell';
import { FeatureSegmentCell } from 'component/common/Table/cells/FeatureSegmentCell/FeatureSegmentCell';
import { useUiFlag } from 'hooks/useUiFlag';
import { FeatureToggleListActions } from './FeatureToggleListActions/FeatureToggleListActions';
import useLoading from 'hooks/useLoading';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { useFeedback } from '../../feedbackNew/useFeedback';
import ReviewsOutlined from '@mui/icons-material/ReviewsOutlined';

export const featuresPlaceholder = Array(15).fill({
    name: 'Name of the feature',
    description: 'Short description of the feature',
    type: '-',
    createdAt: new Date(2022, 1, 1),
    project: 'projectID',
});

const columnHelper = createColumnHelper<FeatureSearchResponseSchema>();
const feedbackCategory = 'search';

export const FeatureToggleListTable: VFC = () => {
    const theme = useTheme();
    const featureSearchFeedback = useUiFlag('featureSearchFeedback');
    const { trackEvent } = usePlausibleTracker();
    const { environments } = useEnvironments();
    const enabledEnvironments = environments
        .filter((env) => env.enabled)
        .map((env) => env.name);
    const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
    const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
    const [showExportDialog, setShowExportDialog] = useState(false);

    const { setToastApiError } = useToast();
    const { uiConfig } = useUiConfig();

    const variant =
        featureSearchFeedback !== false
            ? featureSearchFeedback?.name ?? ''
            : '';

    const { openFeedback } = useFeedback(
        feedbackCategory,
        'automatic',
        variant,
    );

    const stateConfig = {
        offset: withDefault(NumberParam, 0),
        limit: withDefault(NumberParam, DEFAULT_PAGE_LIMIT),
        query: StringParam,
        favoritesFirst: withDefault(BooleansStringParam, true),
        sortBy: withDefault(StringParam, 'createdAt'),
        sortOrder: withDefault(StringParam, 'desc'),
        project: FilterItemParam,
        tag: FilterItemParam,
        state: FilterItemParam,
        segment: FilterItemParam,
        createdAt: FilterItemParam,
    };
    const [tableState, setTableState] = usePersistentTableState(
        'features-list-table',
        stateConfig,
    );
    const {
        offset,
        limit,
        query,
        favoritesFirst,
        sortBy,
        sortOrder,
        ...filterState
    } = tableState;

    const {
        features = [],
        total,
        loading,
        refetch: refetchFeatures,
        initialLoad,
    } = useFeatureSearch(
        mapValues(encodeQueryParams(stateConfig, tableState), (value) =>
            value ? `${value}` : undefined,
        ),
    );
    const bodyLoadingRef = useLoading(loading);
    const { favorite, unfavorite } = useFavoriteFeaturesApi();
    const onFavorite = useCallback(
        async (feature: FeatureSchema) => {
            try {
                if (feature?.favorite) {
                    await unfavorite(feature.project!, feature.name);
                } else {
                    await favorite(feature.project!, feature.name);
                }
                refetchFeatures();
            } catch (error) {
                setToastApiError(
                    'Something went wrong, could not update favorite',
                );
            }
        },
        [favorite, refetchFeatures, unfavorite, setToastApiError],
    );

    const columns = useMemo(
        () => [
            columnHelper.accessor('favorite', {
                header: () => (
                    <FavoriteIconHeader
                        isActive={favoritesFirst}
                        onClick={() =>
                            setTableState({
                                favoritesFirst: !favoritesFirst,
                            })
                        }
                    />
                ),
                cell: ({ getValue, row }) => (
                    <>
                        <FavoriteIconCell
                            value={getValue()}
                            onClick={() => onFavorite(row.original)}
                        />
                    </>
                ),
                enableSorting: false,
                meta: {
                    width: '1%',
                },
            }),
            columnHelper.accessor('lastSeenAt', {
                header: 'Seen',
                cell: ({ row }) => (
                    <FeatureEnvironmentSeenCell feature={row.original} />
                ),
                meta: {
                    align: 'center',
                    width: '1%',
                },
            }),
            columnHelper.accessor('type', {
                header: 'Type',
                cell: ({ getValue }) => <FeatureTypeCell value={getValue()} />,
                meta: {
                    align: 'center',
                    width: '1%',
                },
            }),
            columnHelper.accessor('name', {
                header: 'Name',
                // cell: (cell) => <FeatureNameCell value={cell.row} />,
                cell: ({ row }) => (
                    <LinkCell
                        title={row.original.name}
                        subtitle={row.original.description || undefined}
                        to={`/projects/${row.original.project}/features/${row.original.name}`}
                    />
                ),
                meta: {
                    width: '50%',
                },
            }),
            columnHelper.accessor((row) => row.segments?.join('\n') || '', {
                header: 'Segments',
                cell: ({ getValue, row }) => (
                    <FeatureSegmentCell value={getValue()} row={row} />
                ),
                enableSorting: false,
                meta: {
                    width: '1%',
                },
            }),
            columnHelper.accessor(
                (row) =>
                    row.tags
                        ?.map(({ type, value }) => `${type}:${value}`)
                        .join('\n') || '',
                {
                    header: 'Tags',
                    cell: FeatureTagCell,
                    enableSorting: false,
                    meta: {
                        width: '1%',
                    },
                },
            ),
            columnHelper.accessor('createdAt', {
                header: 'Created',
                cell: ({ getValue }) => <DateCell value={getValue()} />,
                meta: {
                    width: '1%',
                },
            }),
            columnHelper.accessor('project', {
                header: 'Project ID',
                cell: ({ getValue }) => (
                    <LinkCell
                        title={getValue()}
                        to={`/projects/${getValue()}`}
                    />
                ),
                meta: {
                    width: '1%',
                },
            }),
            columnHelper.accessor('stale', {
                header: 'State',
                cell: ({ getValue }) => <FeatureStaleCell value={getValue()} />,
                meta: {
                    width: '1%',
                },
            }),
        ],
        [favoritesFirst],
    );

    const data = useMemo(
        () =>
            features?.length === 0 && loading ? featuresPlaceholder : features,
        [initialLoad, features, loading],
    );

    const table = useReactTable(
        withTableState(tableState, setTableState, {
            columns,
            data,
        }),
    );

    useEffect(() => {
        if (isSmallScreen) {
            table.setColumnVisibility({
                type: false,
                createdAt: false,
                tags: false,
                lastSeenAt: false,
                stale: false,
            });
        } else if (isMediumScreen) {
            table.setColumnVisibility({
                lastSeenAt: false,
                stale: false,
            });
        } else {
            table.setColumnVisibility({});
        }
    }, [isSmallScreen, isMediumScreen]);

    const setSearchValue = (query = '') => {
        setTableState({ query });
        trackEvent('search-bar', {
            props: {
                screen: 'features',
                length: query.length,
            },
        });
    };

    const rows = table.getRowModel().rows;

    if (!(environments.length > 0)) {
        return null;
    }

    const createFeedbackContext = () => {
        openFeedback({
            title: 'How easy was it to use search and filters?',
            positiveLabel: 'What do you like most about search and filters?',
            areasForImprovementsLabel:
                'What should be improved in search and filters page?',
        });
    };

    return (
        <PageContent
            disableLoading={true}
            bodyClass='no-padding'
            header={
                <PageHeader
                    title='Search'
                    actions={
                        <>
                            <ConditionallyRender
                                condition={!isSmallScreen}
                                show={
                                    <>
                                        <Search
                                            placeholder='Search'
                                            expandable
                                            initialValue={query || ''}
                                            onChange={setSearchValue}
                                            id='globalFeatureToggles'
                                        />
                                        <PageHeader.Divider />
                                    </>
                                }
                            />
                            <Link
                                component={RouterLink}
                                to='/archive'
                                underline='always'
                                sx={{ marginRight: 2, ...focusable(theme) }}
                                onClick={() => {
                                    trackEvent('search-feature-buttons', {
                                        props: {
                                            action: 'archive',
                                        },
                                    });
                                }}
                            >
                                View archive
                            </Link>
                            <FeatureToggleListActions
                                onExportClick={() => setShowExportDialog(true)}
                            />
                            {featureSearchFeedback !== false &&
                                featureSearchFeedback?.enabled && (
                                    <>
                                        <ConditionallyRender
                                            condition={
                                                variant === 'withoutText'
                                            }
                                            show={
                                                <Tooltip
                                                    title='Provide feedback'
                                                    arrow
                                                >
                                                    <IconButton
                                                        onClick={
                                                            createFeedbackContext
                                                        }
                                                        size='large'
                                                    >
                                                        <ReviewsOutlined />
                                                    </IconButton>
                                                </Tooltip>
                                            }
                                        />
                                        <ConditionallyRender
                                            condition={variant === 'withText'}
                                            show={
                                                <Button
                                                    startIcon={
                                                        <ReviewsOutlined />
                                                    }
                                                    onClick={
                                                        createFeedbackContext
                                                    }
                                                >
                                                    Provide feedback
                                                </Button>
                                            }
                                        />{' '}
                                        <ConditionallyRender
                                            condition={
                                                variant === 'withTextOutlined'
                                            }
                                            show={
                                                <Button
                                                    startIcon={
                                                        <ReviewsOutlined />
                                                    }
                                                    onClick={
                                                        createFeedbackContext
                                                    }
                                                    variant='outlined'
                                                >
                                                    Provide feedback
                                                </Button>
                                            }
                                        />
                                    </>
                                )}
                        </>
                    }
                >
                    <ConditionallyRender
                        condition={isSmallScreen}
                        show={
                            <Search
                                initialValue={query || ''}
                                onChange={setSearchValue}
                                id='globalFeatureToggles'
                            />
                        }
                    />
                </PageHeader>
            }
        >
            <FeatureToggleFilters
                onChange={setTableState}
                state={filterState}
            />
            <SearchHighlightProvider value={query || ''}>
                <div ref={bodyLoadingRef}>
                    <PaginatedTable tableInstance={table} totalItems={total} />
                </div>
            </SearchHighlightProvider>
            <ConditionallyRender
                condition={rows.length === 0}
                show={
                    <Box sx={(theme) => ({ padding: theme.spacing(0, 2, 2) })}>
                        <ConditionallyRender
                            condition={(query || '')?.length > 0}
                            show={
                                <TablePlaceholder>
                                    No feature toggles found matching &ldquo;
                                    {query}
                                    &rdquo;
                                </TablePlaceholder>
                            }
                            elseShow={
                                <TablePlaceholder>
                                    No feature toggles found matching your
                                    criteria. Get started by adding a new
                                    feature toggle.
                                </TablePlaceholder>
                            }
                        />
                    </Box>
                }
            />
            <ConditionallyRender
                condition={Boolean(uiConfig?.flags?.featuresExportImport)}
                show={
                    <ExportDialog
                        showExportDialog={showExportDialog}
                        data={data}
                        onClose={() => setShowExportDialog(false)}
                        environments={enabledEnvironments}
                    />
                }
            />
        </PageContent>
    );
};
