import React, { useEffect, useState } from 'react';
import { Alert, Card } from '@theorchard/suite-components';
import AssetReportTable from 'src/components/assetReport/assetReportTable';
import { ASSET_STATUS } from 'src/components/assetReport/types';
import UnidentifiedAssetsSidebar from 'src/components/assetReport/unidentifiedAssetsSidebar';
import { useGetBulkAssetReportQuery } from 'src/data/queries/getBulkAssetReport';
import type { GridTableSortBy } from '@theorchard/suite-components';
import type { Product } from 'src/components/assetReport/types';
import type { BulkSessionAssetSortBy, OrderDir } from 'src/data/globalTypes';

const AssetReport = ({
    bulkSessionId,
    refreshAssets,
    setRefreshAssets,
    totalProductCount,
    setTotalProductCount,
    setCompleteProductCount,
    setDownloadLink,
    unidentifiedAssets,
    uploadingFilenames,
}: {
    bulkSessionId: string;
    refreshAssets: boolean;
    setRefreshAssets: (value: boolean) => void;
    totalProductCount: number;
    setTotalProductCount: (value: number) => void;
    setCompleteProductCount: (value: number) => void;
    setDownloadLink: (value: string) => void;
    unidentifiedAssets: string[];
    uploadingFilenames?: string[];
}) => {
    const [isSidebarOpen, setIsSidebarOpen] = useState(false);
    const [products, setProducts] = useState<Product[] | null>(null);
    const [loading, setLoading] = useState(true);
    const [pageNumber, setPageNumber] = useState(0);
    const [pageSize, setPageSize] = useState(10);
    const [sortKey, setSortKey] = useState<BulkSessionAssetSortBy | undefined>(
        undefined
    );
    const [sortDirection, setSortDirection] = useState<OrderDir | undefined>(
        undefined
    );

    const getBulkAssetReport = useGetBulkAssetReportQuery();

    interface MapProductsResult {
        products: Product[];
        isInProgress: boolean;
    }

    const mapProducts = (
        products: {
            productName: string;
            productCode: string;
            artwork: {
                status: string;
                errors: string[] | null;
                filename: string | null;
            };
            tracks: {
                trackName: string;
                status: string;
                errors: string[] | null;
                filename: string | null;
            }[];
        }[]
    ): MapProductsResult => {
        let isInProgress = false;
        const mappedProducts = products.map(p => {
            const artworkStatus = p.artwork.status as ASSET_STATUS;
            isInProgress =
                artworkStatus === ASSET_STATUS.InProgress || isInProgress;
            return {
                productName: p.productName,
                productCode: p.productCode,
                artwork: {
                    status: artworkStatus,
                    errors: p.artwork.errors,
                    filename: p.artwork.filename,
                },
                tracks: p.tracks.map(t => {
                    const trackStatus = t.status as ASSET_STATUS;
                    isInProgress =
                        trackStatus === ASSET_STATUS.InProgress || isInProgress;
                    return {
                        trackName: t.trackName,
                        status: trackStatus,
                        errors: t.errors,
                        filename: t.filename,
                    };
                }),
            };
        });

        return {
            products: mappedProducts,
            isInProgress,
        };
    };

    useEffect(() => {
        if (refreshAssets) {
            getBulkAssetReport(
                bulkSessionId,
                true,
                true,
                pageSize,
                pageNumber * pageSize,
                sortKey,
                sortDirection
            )
                .then(async result => {
                    if (result) {
                        const { products, isInProgress } = mapProducts(
                            result.products
                        );
                        setProducts(products);
                        setRefreshAssets(isInProgress);
                        setTotalProductCount(result.totalProductCount);
                        setCompleteProductCount(result.completeProductCount);
                        setDownloadLink(result.downloadLink ?? '');
                    }
                    setLoading(false);
                    if (refreshAssets) {
                        // slow polling to improve UX
                        await new Promise(r => setTimeout(r, 2000));
                    }
                })
                .catch(() => {
                    setLoading(false);
                });
        }
    }, [
        bulkSessionId,
        getBulkAssetReport,
        refreshAssets,
        setDownloadLink,
        setTotalProductCount,
        setCompleteProductCount,
        setRefreshAssets,
    ]);

    const handleSort = (newSort: GridTableSortBy[]) => {
        setLoading(true);
        getBulkAssetReport(
            bulkSessionId,
            false,
            false,
            pageSize,
            0,
            newSort[0].key as BulkSessionAssetSortBy,
            newSort[0].direction.toUpperCase() as OrderDir
        )
            .then(result => {
                setLoading(false);
                if (result) {
                    const { products, isInProgress } = mapProducts(
                        result.products
                    );
                    setSortKey(newSort[0].key as BulkSessionAssetSortBy);
                    setSortDirection(
                        newSort[0].direction.toUpperCase() as OrderDir
                    );
                    setProducts(products);
                    setRefreshAssets(isInProgress);
                }
            })
            .catch(() => {
                setLoading(false);
            });
    };

    const handlePageSelect = (page: number) => {
        const offset = page * pageSize;

        setLoading(true);
        getBulkAssetReport(
            bulkSessionId,
            false,
            false,
            pageSize,
            offset,
            sortKey,
            sortDirection
        )
            .then(result => {
                setLoading(false);
                if (result) {
                    const { products, isInProgress } = mapProducts(
                        result.products
                    );
                    setProducts(products);
                    setPageNumber(page);
                    setRefreshAssets(isInProgress);
                }
            })
            .catch(() => {
                setLoading(false);
            });
    };

    const handleChangePageSize = (newSize: number) => {
        setLoading(true);
        getBulkAssetReport(
            bulkSessionId,
            false,
            false,
            newSize,
            0,
            sortKey,
            sortDirection
        )
            .then(result => {
                setLoading(false);
                if (result) {
                    const { products, isInProgress } = mapProducts(
                        result.products
                    );
                    setProducts(products);
                    setPageSize(newSize);
                    setRefreshAssets(isInProgress);
                }
            })
            .catch(() => {
                setLoading(false);
            });
    };

    return (
        <Card suite className="error-summary-report">
            <Card.Header>
                <Card.Title>
                    {$t('bulkDigitalAudio.assetReport.uploads')}
                </Card.Title>
            </Card.Header>
            <Card.Body className="asset-report-body">
                {unidentifiedAssets.length > 0 && (
                    <Alert
                        variant="information"
                        className="unidentified-assets-alert"
                        text={$t(
                            'bulkDigitalAudio.assetReport.unidentifiedAssetsAlert',
                            {
                                numAssets: unidentifiedAssets.length,
                            }
                        )}
                        button={{
                            text: $t(
                                'bulkDigitalAudio.assetReport.viewUnidentifiedAssets'
                            ),
                            variant: 'tertiary',
                            size: 'sm',
                            onClick: () => setIsSidebarOpen(true),
                        }}
                    />
                )}
                <div className="error-report-table">
                    <AssetReportTable
                        loading={loading}
                        products={products}
                        pageNumber={pageNumber}
                        pageSize={pageSize}
                        numProducts={totalProductCount}
                        onPageChange={handlePageSelect}
                        onPageSizeChange={handleChangePageSize}
                        onSort={handleSort}
                        uploadingFilenames={uploadingFilenames}
                    />
                </div>
            </Card.Body>
            <UnidentifiedAssetsSidebar
                unidentifiedAssets={unidentifiedAssets}
                isOpen={isSidebarOpen}
                onClose={() => setIsSidebarOpen(false)}
            />
        </Card>
    );
};

export default AssetReport;
