import React, { useEffect, useState } from 'react';
import { useReactiveVar } from '@apollo/client';
import { Alert } from '@theorchard/suite-components';
import { isEmpty } from 'lodash-es';
import { useHistory, useLocation } from 'react-router-dom';
import { useAccountList } from 'src/apollo/queries/account';
import paginationStateVar from 'src/apollo/reactive-vars/tables-state';
import AccountFilters from 'src/components/account-list/account-filters';
import AccountTable from 'src/components/account-list/account-table';
import { PageHeader } from 'src/components/shared/pageHeader';
import { DEFAULT_ITEMS_PER_PAGE } from 'src/constants';
import usePagination from 'src/hooks/pagination';
import { getQueryParams, updateQueryParam } from 'src/utils/route';
import type { GetAccountsListQuery } from 'src/apollo/queries/account/__generated__/get-accounts-list';
import type {
    AbacusAccountList,
    AbacusAccountFilters,
} from 'src/types/abacus-account';
import './styles.scss';

type AbacusAccount = GetAccountsListQuery['abacusAccounts']['items'][0];

export const AccountList: React.FC = () => {
    const history = useHistory();
    const location = useLocation();
    const [accountList, setAccountList] = useState<AbacusAccountList[] | []>(
        []
    );
    const [filterResultsCount, setFilterResultsCount] = useState<number>(0);
    const itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
    const paginationState = useReactiveVar<any>(paginationStateVar);
    const [isFiltered, setIsFiltered] = useState<boolean>(false);
    const [filterValues, setFilterValues] = useState<{
        limit: number;
        offset: number;
        searchTerm: string;
    }>({
        limit: itemsPerPage,
        offset: 0,
        searchTerm: '',
    });
    const queryParams: any = {
        searchTerm: {
            name: 'searchTerm',
            type: 'string',
        },
    };

    const { data, error, loading } = useAccountList(filterValues);

    const changeHandler = (e: any) => {
        const {
            target: { name, value },
        } = e;
        const key = name as keyof AbacusAccountFilters;
        const filterValue = value.trim();
        setFilterValues({ ...filterValues, offset: 0, [key]: filterValue });
        setIsFiltered(value ? true : false);
        updateQueryParam(location, history, queryParams, key, filterValue);
    };

    const clearFilter = () => {
        setIsFiltered(false);
        setFilterValues({ limit: itemsPerPage, offset: 0, searchTerm: '' });
        updateQueryParam(location, history, queryParams, null, null);
    };

    const formatAccountList = (items: AbacusAccount[] | []) => {
        const accounts = items
            ? items.map((account: AbacusAccount) => {
                  const { accountId, accountName, contracts, vendor } = account;
                  return {
                      accountName,
                      brandName: vendor.companyBrand?.name,
                      accountId,
                      contractsCount: contracts?.length || 0,
                  };
              })
            : [];
        setAccountList(accounts);
    };

    const fetchMoreWrapper = ({ variables: { limit, offset } }: any) => {
        const variables = { ...filterValues, limit, offset };
        setFilterValues(variables);
    };

    const { renderPagination } = usePagination({
        fetchMore: fetchMoreWrapper,
        totalItemCount: filterResultsCount,
        itemsPerPage,
        tableId: 'account-list',
    });

    useEffect(() => {
        const parsedParams = getQueryParams(location, queryParams);
        if (!isEmpty(parsedParams)) {
            setFilterValues({ ...filterValues, ...parsedParams });
            setIsFiltered(true);
        }
    }, []);

    useEffect(() => {
        if (data) {
            const {
                abacusAccounts: { items, totalCount },
            } = data;
            formatAccountList(items);
            setFilterResultsCount(totalCount);
        }
    }, [data, isFiltered]);

    useEffect(() => {
        paginationStateVar({
            ...paginationState,
            'account-list': 1,
        });
    }, [filterValues.searchTerm]);

    const { graphqlError, networkErrors, message }: any = error || {};

    return (
        <div className="AccountList SearchableList">
            {graphqlError && (
                <Alert
                    variant="error"
                    text={
                        <span>
                            <strong>GraphQL Error: </strong>
                            {graphqlError}
                        </span>
                    }
                />
            )}
            {networkErrors && (
                <Alert
                    variant="error"
                    text={
                        <span>
                            <strong>Network Message: </strong>
                            {networkErrors}
                        </span>
                    }
                />
            )}
            {message && (
                <Alert
                    variant="error"
                    text={
                        <span>
                            <strong>Error Message: </strong>
                            {message}
                        </span>
                    }
                />
            )}

            <PageHeader title="Accounts" />
            <AccountFilters
                changeHandler={changeHandler}
                clearFilters={clearFilter}
                isFiltered={isFiltered}
                filterValues={filterValues}
                setFilterValues={setFilterValues}
            />
            <AccountTable
                accountList={accountList}
                isFiltered={isFiltered}
                isLoading={loading}
                renderPagination={renderPagination}
            />
        </div>
    );
};
