import classnames from 'classnames';
import { action } from 'mobx';
import { FC, useCallback } from 'react';
import { observer, useLocalStore } from 'mobx-react';

import {
    BodyText,
    Button,
    Card,
    Container,
    Form,
    Grid,
    Layout,
    Link,
    Stack,
    Text,
    Tooltip,
} from '@servicetitan/design-system';
import {
    DateRangeColumnMenuFilter,
    multiSelectColumnMenuFilter,
    StandardColumnMenuFilter,
    Table,
    TableColumn,
    TableState,
    TableCellProps,
} from '@servicetitan/table';

import { ResultDefinitionsModal } from '../result-definitions-modal';

interface EmailValidationLocalStore {
    open: boolean;
    setOpen(state: boolean): void;
}

export interface EmailValidationTableRecord<T> {
    id: number;
    active: boolean;
    createdOn: Date;
    email?: string | undefined;
    result: T;
    dateAdded?: Date | undefined;
}

export interface EmailValidationProps<
    TEmailValidationType extends string | number = string,
    TEmailValidationResult extends string | number = string,
> {
    className?: string;
    loading: boolean;
    resultGrid: TableState<EmailValidationTableRecord<TEmailValidationResult>>;
    validationRiskType?: TEmailValidationType;
    handleDownload(): void;
    setValidationRiskType(type: TEmailValidationType): void;
}

interface EmailValidationHocOptions<
    TEmailValidationType extends string | number = string,
    TEmailValidationResult extends string | number = string,
> {
    resultToText: Map<TEmailValidationResult, string>;
    levelTypeMap: {
        high: TEmailValidationType;
        medium: TEmailValidationType;
        low: TEmailValidationType;
    };
    levelResultMap: Map<TEmailValidationType, TEmailValidationResult[]>;
    resultToTooltipText: Map<TEmailValidationResult, string>;
    TenantDateCell: FC<TableCellProps>;
}

export function emailValidationHoc<
    TEmailValidationType extends string | number = string,
    TEmailValidationResult extends string | number = string,
>({
    resultToText,
    levelTypeMap,
    resultToTooltipText,
    levelResultMap,
    TenantDateCell,
}: EmailValidationHocOptions<TEmailValidationType, TEmailValidationResult>) {
    const ResultColumnMenuFilter = multiSelectColumnMenuFilter(
        [...resultToText.keys()],
        result => resultToText.get(result)!,
    );

    const ResultCell: FC<TableCellProps> = props => {
        const { result } = props.dataItem as { result: TEmailValidationResult };

        return (
            <td className="qa-result-cell of-visible-i">
                <Tooltip text={resultToTooltipText.get(result)} className="qa-result-cell-tooltip">
                    {resultToText.get(result)}
                </Tooltip>
            </td>
        );
    };

    function EmailValidationImpl({
        className,
        handleDownload,
        loading,
        resultGrid,
        setValidationRiskType,
        validationRiskType,
    }: EmailValidationProps<TEmailValidationType, TEmailValidationResult>) {
        const localStore: EmailValidationLocalStore = useLocalStore(() => ({
            open: false,
            setOpen: action(function (this: EmailValidationLocalStore, state: boolean) {
                this.open = state;
            }),
        }));

        const handleCheck = useCallback(
            (riskType: TEmailValidationType) => () => {
                setValidationRiskType(riskType);
            },
            [setValidationRiskType],
        );

        const handleClickLearnMore = () => {
            localStore.setOpen(true);
        };

        const handleClose = () => {
            localStore.setOpen(false);
        };

        const getResultsItemsForLevel = (level: TEmailValidationType) => {
            return levelResultMap
                .get(level)
                ?.map(r => resultToText.get(r))
                .map(r => <div key={r}>{r}</div>);
        };

        return (
            <Container className={classnames(className, 'p-b-5 qa-email-validation')}>
                <Stack justifyContent="space-between" alignItems="center" className="m-b-2">
                    <Text size={4} className="m-r-3">
                        Email Validation
                    </Text>
                    <Button
                        small
                        primary
                        onClick={handleDownload}
                        className="qa-email-validation-download-csv"
                        iconName="file_download"
                        iconPosition="left"
                    >
                        Download CSV
                    </Button>
                </Stack>
                <Layout type="support" direction="right">
                    <Layout.Section>
                        <Text size={2} className="m-b-4 c-neutral-90">
                            Email Validation acts like a filter that will block emails from going to
                            bad email addresses. You won't necessarily see these emails in your
                            suppression list, but it will effect your number “Sent”.
                        </Text>
                    </Layout.Section>
                    <Layout.Section />
                </Layout>
                <Grid relaxed>
                    <Grid.Column width={3}>
                        <Card>
                            <Card.Section light>
                                <Text bold size={3} className="m-b-1">
                                    Set Your Preference
                                </Text>
                                <Text size={2} className="m-b-1">
                                    Choose what level you want to enable for auto-suppression.
                                </Text>
                                <Link
                                    primary
                                    onClick={handleClickLearnMore}
                                    className="qa-email-validation-learn-more"
                                >
                                    Learn More
                                </Link>
                            </Card.Section>
                            <Card.Section>
                                <Form.Radio
                                    label={
                                        <div className="m-l-1">
                                            <Text bold size={3} className="m-b-1">
                                                High
                                                <span className="c-neutral-90 fs-1 m-l-1">
                                                    (recommended)
                                                </span>
                                            </Text>
                                            <BodyText size="small" className="c-neutral-90">
                                                {getResultsItemsForLevel(levelTypeMap.high)}
                                            </BodyText>
                                        </div>
                                    }
                                    checked={validationRiskType === levelTypeMap.high}
                                    onChange={handleCheck(levelTypeMap.high)}
                                    className="qa-email-validation-high"
                                />
                            </Card.Section>
                            <Card.Section>
                                <Form.Radio
                                    label={
                                        <div className="m-l-1">
                                            <Text bold size={3} className="m-b-1">
                                                Medium
                                            </Text>
                                            <BodyText size="small" className="c-neutral-90">
                                                {getResultsItemsForLevel(levelTypeMap.medium)}
                                            </BodyText>
                                        </div>
                                    }
                                    checked={validationRiskType === levelTypeMap.medium}
                                    onChange={handleCheck(levelTypeMap.medium)}
                                    className="qa-email-validation-medium"
                                />
                            </Card.Section>
                            <Card.Section>
                                <Form.Radio
                                    label={
                                        <div className="m-l-1">
                                            <Text bold size={3} className="m-b-1">
                                                Low
                                            </Text>
                                            <BodyText size="small" className="c-neutral-90">
                                                {getResultsItemsForLevel(levelTypeMap.low)}
                                            </BodyText>
                                        </div>
                                    }
                                    checked={validationRiskType === levelTypeMap.low}
                                    onChange={handleCheck(levelTypeMap.low)}
                                    className="qa-email-validation-low"
                                />
                            </Card.Section>
                        </Card>
                    </Grid.Column>
                    <Grid.Column width={9}>
                        <Table
                            tableState={resultGrid}
                            sortable
                            loading={loading}
                            className="qa-email-validation-table"
                            scrollable="none"
                        >
                            <TableColumn
                                field="email"
                                title="Email Address"
                                columnMenu={StandardColumnMenuFilter}
                            />
                            <TableColumn
                                field="result"
                                title="Result"
                                cell={ResultCell}
                                columnMenu={ResultColumnMenuFilter}
                            />
                            <TableColumn
                                field="dateAdded"
                                title="Date Added"
                                cell={TenantDateCell}
                                columnMenu={DateRangeColumnMenuFilter}
                            />
                        </Table>
                    </Grid.Column>
                </Grid>
                {localStore.open && <ResultDefinitionsModal onClose={handleClose} />}
            </Container>
        );
    }
    return observer(EmailValidationImpl);
}
