import type { FC } from 'react';
import React from 'react';
import { Alert, GridTable, Pill } from '@theorchard/suite-components';
import { GlyphIcon, Illustration } from '@theorchard/suite-icons';
import { ReportErrorKey, ReportStatus } from 'src/data/globalTypes';
import { useDeleteChangelogReport } from 'src/data/mutations';
import { parseReportsData } from '../../utils/parseReportsData';
import { REPORT_LAYOUTS } from './constants';
import type { SortBy } from './types';
import type {
    ChangelogReport,
    KeysWithNever,
    ParsedChangelogReport,
} from '../../types';
import type { I18nTerms } from 'src/../../locale/types';

const CLASSNAME = 'SongChangesTable';

interface Props {
    reports: ChangelogReport[];
    pageSize: number;
    page: number;
    totalCount: number;
    sortBy: SortBy[];
    loading: boolean;
    setPage: (page: number) => void;
    setPageSize: (pageSize: number) => void;
    onSort: (sortBy: SortBy[]) => void;
    refetch: () => void;
}

const SongChangesTable: FC<Props> = ({
    reports,
    pageSize,
    page,
    totalCount,
    sortBy,
    loading,
    setPage,
    setPageSize,
    onSort,
    refetch,
}) => {
    const parsedReports = parseReportsData(reports);

    const numPages = Math.ceil(totalCount / pageSize);
    const { deleteChangelogReport } = useDeleteChangelogReport();

    const getErrorMessage = (data: ParsedChangelogReport) => {
        const errorMessages: Record<ReportErrorKey, string | JSX.Element> = {
            [ReportErrorKey.NO_COMPOSITIONS]: $t(
                'tools.pubSongChangesPage.noCompositionsErrorMsg'
            ),
            [ReportErrorKey.NO_UPDATES]: $t(
                'tools.pubSongChangesPage.noUpdatesErrorMsg'
            ),
            [ReportErrorKey.OTHER_ERROR]: (
                <>
                    {$t('tools.pubSongChangesPage.otherErrorMsg')}{' '}
                    <a href="mailto:product-support@theorchard.com">
                        product-support@theorchard.com
                    </a>
                </>
            ),
        };

        return errorMessages[
            data.errorMetadata?.errorKey ?? ReportErrorKey.OTHER_ERROR
        ];
    };

    return (
        <GridTable
            className={CLASSNAME}
            rowKey={row => row.id}
            paginated={numPages > 1}
            page={page}
            pageSize={pageSize}
            sortBy={sortBy}
            onPageChange={setPage}
            onPageSizeChange={setPageSize}
            onSort={onSort}
            totalCount={totalCount}
            data={parsedReports}
            emptyStateIcon={() => <Illustration name="emptyState" />}
            emptyStateTitle={$t('tools.pubSongChangesPage.noResults')}
            emptyStateBody={$t('tools.pubSongChangesPage.noResultsMessage')}
            loading={loading}
            showUpdateIndicator
            rowActionsHeader="Action"
            columnDefs={[
                {
                    name: 'date',
                    title: $t(
                        'tools.pubSongChangesPage.changelogTable.headers.generationDateHeader'
                    ),
                    sortable: true,
                    minWidth: '10%',
                    maxWidth: '20%',
                    align: 'right',
                },
                {
                    name: 'layout',
                    title: $t(
                        'tools.pubSongChangesPage.changelogTable.headers.reportLayoutHeader'
                    ),
                    Cell: ({ data }) => {
                        let statusIcon;
                        switch (data.status) {
                            case ReportStatus.IN_PROGRESS:
                                statusIcon = (
                                    <GlyphIcon name="inProgress" size={16} />
                                );
                                break;
                            case ReportStatus.ERROR:
                                statusIcon = (
                                    <Pill
                                        testId="error-pill"
                                        iconCategory="glyph"
                                        iconName="warning"
                                        popoverOptions={{
                                            id: 'errorPopover',
                                            content: (
                                                <Alert
                                                    testId="error-alert"
                                                    variant="error"
                                                    text={getErrorMessage(data)}
                                                />
                                            ),
                                        }}
                                    />
                                );
                                break;
                            default:
                                statusIcon = '';
                        }

                        return (
                            <span>
                                {statusIcon}{' '}
                                {$t(
                                    REPORT_LAYOUTS[
                                        data.layout
                                    ] as KeysWithNever<I18nTerms>
                                )}
                            </span>
                        );
                    },
                },
                {
                    name: 'period',
                    title: $t(
                        'tools.pubSongChangesPage.changelogTable.headers.timePeriodHeader'
                    ),
                    sortable: false,
                },
                {
                    name: 'generatedBy',
                    title: $t(
                        'tools.pubSongChangesPage.changelogTable.headers.generatedByHeader'
                    ),
                    sortable: false,
                },
            ]}
            rowActions={{
                download: {
                    renderIcon: data => {
                        if (data.status !== ReportStatus.COMPLETE)
                            return <GlyphIcon name="download" size={16} />;
                        return (
                            <a href={data.outputFileUrl || ''}>
                                <GlyphIcon name="download" size={16} />
                            </a>
                        );
                    },
                    disabled: data => data.status !== ReportStatus.COMPLETE,
                },
                delete: {
                    icon: <GlyphIcon name="trash" size={16} />,
                    onClick: async ({ id }) => {
                        await deleteChangelogReport({
                            variables: { id },
                        });
                        refetch();
                    },
                    disabled: data => data.status === ReportStatus.IN_PROGRESS,
                },
            }}
        />
    );
};

export default SongChangesTable;
