import React from 'react';
import { Text, View } from 'react-native';
import numeral from 'numeral';
import {
    STREAMS_1_DAY_SORT,
    STREAMS_28_DAYS_SORT,
    STREAMS_7_DAYS_SORT,
    STREAMS_ALL_TIME_SORT,
    _1_DAY,
    _7_DAYS,
    _28_DAYS,
    STREAMS_1_DAY,
    STREAMS_7_DAYS,
    STREAMS_28_DAYS,
    ABSOLUTE_CHANGE
} from '../../constants/sorting';
import type { _183_DAYS, _365_DAYS } from '../../constants/sorting';
import { STREAM_COUNT_FORMAT } from '../../constants';
import GrowthPercentage from '../GrowthPercentage';
import { safeWithTheme } from '../../branding';
import type { ThemeProps } from '../../branding/hoc/types';
import styles, { type Styles } from './styles';

type Period =
    | typeof _1_DAY
    | typeof _7_DAYS
    | typeof _28_DAYS
    | typeof _183_DAYS
    | typeof _365_DAYS;

interface GrowthPeriodData {
    period: Period;
    value: number;
    prevValue: number;
    growthPercentage: number;
}

interface StreamData {
    aggregate: {
        allTime: number;
    };
    growthPeriods?: GrowthPeriodData[];
}

interface StreamsAndGrowth {
    value: number | undefined;
    growthPercentage?: number;
}

/**
 * @deprecated
 *
 * We should not use the client side "sortKey", but rather the GraphQL values for "order by".
 */
const getStreamsAndGrowth = ({
    streams,
    sortKey
}: {
    streams: StreamData;
    sortKey: string | undefined;
}): StreamsAndGrowth => {
    if (sortKey === STREAMS_ALL_TIME_SORT) {
        return { value: streams?.aggregate?.allTime };
    }
    const periodMap: Partial<Record<string, string>> = {
        [STREAMS_1_DAY_SORT]: _1_DAY,
        [`${STREAMS_1_DAY}_${ABSOLUTE_CHANGE}`]: _1_DAY,
        [STREAMS_7_DAYS_SORT]: _7_DAYS,
        [`${STREAMS_7_DAYS}_${ABSOLUTE_CHANGE}`]: _7_DAYS,
        [STREAMS_28_DAYS_SORT]: _28_DAYS,
        [`${STREAMS_28_DAYS}_${ABSOLUTE_CHANGE}`]: _28_DAYS
    };
    const found = streams?.growthPeriods?.find(
        ({ period }) => period === periodMap[sortKey ?? '']
    );
    return { value: found?.value, growthPercentage: found?.growthPercentage };
};

const orderKeyToGrowthPeriod = ({
    streams,
    orderBy
}: {
    streams: StreamData;
    orderBy: string;
}): StreamsAndGrowth => {
    const mapping: Partial<Record<string, string>> = {
        [STREAMS_1_DAY_SORT]: _1_DAY,
        [STREAMS_1_DAY]: _1_DAY,
        [`${STREAMS_1_DAY}_${ABSOLUTE_CHANGE}`]: _1_DAY,
        [STREAMS_7_DAYS_SORT]: _7_DAYS,
        [STREAMS_7_DAYS]: _7_DAYS,
        [`${STREAMS_7_DAYS}_${ABSOLUTE_CHANGE}`]: _7_DAYS,
        [STREAMS_28_DAYS_SORT]: _28_DAYS,
        [STREAMS_28_DAYS]: _28_DAYS,
        [`${STREAMS_28_DAYS}_${ABSOLUTE_CHANGE}`]: _28_DAYS
    };

    if (!Object.keys(mapping).includes(orderBy)) {
        return { value: streams?.aggregate?.allTime };
    }

    const found = streams?.growthPeriods?.find(
        ({ period }) => period === mapping[orderBy]
    );

    if (!orderBy.includes(ABSOLUTE_CHANGE)) {
        return {
            value: found?.value,
            growthPercentage: found?.growthPercentage
        };
    }
    return {
        value: found?.prevValue
            ? found?.value - found?.prevValue
            : found?.value,
        growthPercentage: found?.growthPercentage
    };
};

interface GrowthPeriodProps {
    streams: StreamData;
    orderBy?: string;
    sortKey?: string;
}

export const GrowthPeriod = ({
    streams,
    orderBy,
    sortKey,
    theme,
    typography
}: GrowthPeriodProps & ThemeProps) => {
    const { value, growthPercentage } = orderBy
        ? orderKeyToGrowthPeriod({ streams, orderBy })
        : getStreamsAndGrowth({ streams, sortKey });
    const themeStyles = styles[theme] as unknown as Styles;

    return (
        <View testID="growthPeriod">
            <Text
                testID="streamCount"
                style={[typography.body1DS, themeStyles.streamCount]}
            >
                {value === null || value === undefined
                    ? '–'
                    : numeral(value).format(STREAM_COUNT_FORMAT).toUpperCase()}
            </Text>
            {Boolean(growthPercentage) && (
                <GrowthPercentage
                    value={growthPercentage || 0}
                    textAlign="right"
                />
            )}
        </View>
    );
};

export default safeWithTheme(GrowthPeriod);
