import React, { useState, useMemo, useEffect } from 'react';
import {
    ErrorMessage,
    GlyphButton,
    GridTable,
    Section,
    Select,
    type SelectOption,
    Status,
    useFullscreenModal,
} from '@theorchard/suite-components';
import type { CollaboratorsDpPaymentsQuery } from 'src/apollo/queries/collaborators/__generated__/dp-payments';
import { uniqBy, snakeCase } from 'lodash-es';
import {
    DpPayoneerPaymentStatus,
    type SortDir,
} from 'src/apollo/definitions/globalTypes';
import { useCollaboratorsDpPaymentsQuery } from 'src/apollo/queries/collaborators/dp-payments';
import PayeeDetailsModal from 'src/components/payee-management/payee-details-modal';
import { smartFormatter } from 'src/utils/amount-helpers';
import { DEFAULT_ITEMS_PER_PAGE } from 'src/constants';
import { EMPTY_CHAR } from '@theorchard/accounting-apps-shared';
import './styles.scss';

const CLASS_NAME = 'DpPayments';

const PAYMENT_STATUS_LABELS: Record<string, string> = {
    [DpPayoneerPaymentStatus.INIT]: 'Pending',
    [DpPayoneerPaymentStatus.RUNNING]: 'Pending',
    [DpPayoneerPaymentStatus.COMPLETE]: 'Successful',
    [DpPayoneerPaymentStatus.REJECTED]: 'Cancelled',
    [DpPayoneerPaymentStatus.ERROR]: 'Error',
};

type Payment = CollaboratorsDpPaymentsQuery['dpPayments']['payments'][number];

type Variant = React.ComponentProps<typeof Status>['variant'];

const renderPaymentStatus = (paymentStatus: string | null) => {
    const [variant, message] = (() => {
        switch (paymentStatus) {
            case DpPayoneerPaymentStatus.INIT:
            case DpPayoneerPaymentStatus.RUNNING:
                return ['warning', 'Pending'];
            case DpPayoneerPaymentStatus.COMPLETE:
                return ['success', 'Successful'];
            case DpPayoneerPaymentStatus.REJECTED:
                return ['error', 'Cancelled'];
            case DpPayoneerPaymentStatus.ERROR:
                return ['error', 'Error'];
            default:
                return ['neutral', ''];
        }
    })();

    return <Status variant={variant as Variant} text={message} filled />;
};

const PayoneerStatusCell = ({
    data: { payoneerPaymentStatus },
}: {
    data: Pick<Payment, 'payoneerPaymentStatus'>;
}) => <span>{renderPaymentStatus(payoneerPaymentStatus)}</span>;

const ErrorMessageCell = ({
    data: { latestPayoneerEventReason },
}: {
    data: Pick<Payment, 'latestPayoneerEventReason'>;
}) => <span>{latestPayoneerEventReason || EMPTY_CHAR}</span>;

const AmountCell = ({
    data: { amount, currency },
}: {
    data: Pick<Payment, 'amount' | 'currency'>;
}) => <span>{smartFormatter(amount, currency)}</span>;

const StatementPeriodCell = ({
    data: { abacusStatementPeriodId, abacusStatementPeriodName },
}: {
    data: Pick<
        Payment,
        'abacusStatementPeriodId' | 'abacusStatementPeriodName'
    >;
}) => (
    <span>
        <span>{abacusStatementPeriodName}</span>
        <span className={`${CLASS_NAME}-secondary-text`}>
            {abacusStatementPeriodId}
        </span>
    </span>
);

const CollaboratorCell = ({
    data: { collaboratorName, collaboratorId },
}: {
    data: Pick<Payment, 'collaboratorName' | 'collaboratorId'>;
}) => (
    <span>
        <span>{collaboratorName}</span>
        <span className={`${CLASS_NAME}-secondary-text`}>{collaboratorId}</span>
    </span>
);

const AccountCell = ({
    data: { account },
}: {
    data: Pick<Payment, 'account'>;
}) => (
    <span>
        <span>{account.vendor.name}</span>
        <span className={`${CLASS_NAME}-secondary-text`}>
            {account.accountId}
        </span>
    </span>
);

const ProgramCell = ({
    data: { payoneerProgramId, payoneerProgramName },
}: {
    data: Pick<Payment, 'payoneerProgramId' | 'payoneerProgramName'>;
}) => (
    <span>
        <span>{payoneerProgramName}</span>
        <span className={`${CLASS_NAME}-secondary-text`}>
            {payoneerProgramId}
        </span>
    </span>
);

const PaymentIdCell = ({ data: { id } }: { data: Pick<Payment, 'id'> }) => (
    <span>{id}</span>
);

const PaymentManagement = () => {
    const [statusFilter, setStatusFilter] = useState<
        SelectOption | undefined
    >();
    const [collaboratorFilter, setCollaboratorFilter] = useState<
        SelectOption | undefined
    >();
    const [accountFilter, setAccountFilter] = useState<
        SelectOption | undefined
    >();
    const [statementPeriodFilter, setStatementPeriodFilter] = useState<
        SelectOption | undefined
    >();
    const [sortKey, setSortKey] = useState<string | undefined>();
    const [sortDirection, setSortDirection] = useState<SortDir | undefined>();
    const [selectedRow, setSelectedRow] = useState<{
        collaboratorId: string;
        payeeId: string;
    } | null>(null);

    const { open: openModal, close: closeModal } = useFullscreenModal();
    const [page, setPage] = useState<number>(0);
    const [pageSize, setPageSize] = useState<number>(DEFAULT_ITEMS_PER_PAGE);

    const {
        data: directPaymentsData,
        loading,
        error,
    } = useCollaboratorsDpPaymentsQuery({
        abacusStatementPeriodId: statementPeriodFilter?.value,
        collaboratorId: collaboratorFilter
            ? Number(collaboratorFilter.value)
            : undefined,
        accountId: accountFilter ? Number(accountFilter.value) : undefined,
        payoneerStatus: statusFilter?.value as
            | DpPayoneerPaymentStatus
            | undefined,
        sortKey,
        sortDirection,
    });

    const payments = directPaymentsData?.dpPayments.payments ?? [];

    const [basePayments, setBasePayments] = useState(payments);

    useEffect(() => {
        if (basePayments.length === 0 && payments.length > 0) {
            setBasePayments(payments);
        }
    }, [payments, basePayments]);

    const pagedPayments = useMemo(
        () => payments.slice(page * pageSize, (page + 1) * pageSize),
        [payments, page, pageSize]
    );

    const paymentStatusOptions = useMemo(() => {
        return uniqBy(basePayments, 'payoneerPaymentStatus').map(p => ({
            label:
                PAYMENT_STATUS_LABELS[p.payoneerPaymentStatus as string] ??
                (p.payoneerPaymentStatus as string),
            value: p.payoneerPaymentStatus as string,
        }));
    }, [basePayments]);

    const collaboratorOptions = useMemo(() => {
        return uniqBy(basePayments, 'collaboratorId').map(p => ({
            label: p.collaboratorName,
            subtitle: p.collaboratorId,
            value: p.collaboratorId,
        }));
    }, [basePayments]);

    const accountOptions = useMemo(() => {
        return uniqBy(basePayments, 'account.accountId').map(p => ({
            label: p.account.vendor.name,
            subtitle: p.account.accountId,
            value: p.account.accountId,
        }));
    }, [basePayments]);

    const statementPeriodOptions = useMemo(() => {
        return uniqBy(basePayments, 'abacusStatementPeriodId').map(p => ({
            label: p.abacusStatementPeriodName,
            subtitle: p.abacusStatementPeriodId,
            value: p.abacusStatementPeriodId,
        }));
    }, [basePayments]);

    if (error) {
        return <ErrorMessage error={error} />;
    }

    return (
        <Section>
            <Section.Body>
                <Section.Filters className={`${CLASS_NAME}-filters`}>
                    <Select
                        compact
                        placeholder="Payment Status"
                        options={paymentStatusOptions}
                        onChange={option => {
                            setPage(0);
                            setStatusFilter(option);
                        }}
                        components={{
                            OptionLabel: ({ option }) =>
                                renderPaymentStatus(option.value),
                        }}
                    />
                    <Select
                        compact
                        placeholder="Collaborator Name & ID"
                        options={collaboratorOptions}
                        onChange={option => {
                            setPage(0);
                            setCollaboratorFilter(option);
                        }}
                    />
                    <Select
                        compact
                        placeholder="Account Name & ID"
                        options={accountOptions}
                        onChange={option => {
                            setPage(0);
                            setAccountFilter(option);
                        }}
                    />
                    <Select
                        compact
                        placeholder="Statement Period & ID"
                        options={statementPeriodOptions}
                        onChange={option => {
                            setPage(0);
                            setStatementPeriodFilter(option);
                        }}
                    />
                </Section.Filters>
                <Section.Table>
                    <GridTable
                        loading={loading}
                        data={pagedPayments}
                        variant="zebra"
                        paginated
                        page={page}
                        pageSize={pageSize}
                        totalCount={payments.length}
                        onPageChange={setPage}
                        onPageSizeChange={setPageSize}
                        defaultColumnDefs={{
                            sortable: true,
                            defaultSortDirection: 'asc',
                        }}
                        onSort={e => {
                            setPage(0);
                            setSortKey(snakeCase(e[0].key));
                            setSortDirection(
                                e[0].direction.toUpperCase() as SortDir
                            );
                        }}
                        columnDefs={[
                            {
                                name: 'payoneerStatus',
                                title: 'Payment Status',
                                Cell: PayoneerStatusCell,
                            },
                            {
                                name: 'latestPayoneerEventReason',
                                title: 'Error Message',
                                Cell: ErrorMessageCell,
                            },
                            {
                                name: 'amount',
                                title: 'Amount',
                                align: 'right',
                                Cell: AmountCell,
                            },
                            {
                                name: 'abacusStatementPeriodId',
                                title: 'Statement Period & ID',
                                minWidth: '154px',
                                Cell: StatementPeriodCell,
                            },
                            {
                                name: 'collaboratorName',
                                title: 'Collaborator Name & ID',
                                Cell: CollaboratorCell,
                            },
                            {
                                name: 'accountName',
                                title: 'Account Name & ID',
                                Cell: AccountCell,
                            },
                            {
                                name: 'payoneerProgramName',
                                title: 'Program Name & ID',
                                Cell: ProgramCell,
                            },
                            {
                                name: 'dpPaymentId',
                                title: 'Payment ID',
                                Cell: PaymentIdCell,
                            },
                            {
                                name: 'actions',
                                title: 'Actions',
                                sortable: false,
                                Cell: ({
                                    data: { collaboratorId, payeeId },
                                }) => (
                                    <GlyphButton
                                        name="moreDetails"
                                        tooltip="View Payee Details"
                                        variant="secondary"
                                        onClick={() =>
                                            openModal(() =>
                                                setSelectedRow({
                                                    collaboratorId,
                                                    payeeId,
                                                })
                                            )
                                        }
                                    />
                                ),
                            },
                        ]}
                    />
                </Section.Table>
                {selectedRow && (
                    <PayeeDetailsModal
                        isOpen
                        onRequestClose={() =>
                            closeModal(() => setSelectedRow(null))
                        }
                        collaboratorId={selectedRow.collaboratorId}
                        payeeId={selectedRow.payeeId}
                        showReject={false}
                    />
                )}
            </Section.Body>
        </Section>
    );
};

export default PaymentManagement;
