import React, { type FC, useMemo, useState } from 'react';
import {
    GridTable,
    type GridTableCellProps,
    type GridTableSortBy,
} from '@theorchard/suite-components';
import AssetReportErrors from 'src/components/assetReport/assetReportTable/assetReportErrors';
import AssetReportStatus from 'src/components/assetReport/assetReportTable/assetReportStatus';
import { ASSET_STATUS } from 'src/components/assetReport/types';
import type { Product } from 'src/components/assetReport/types';

const hasErrors = (product: Product) =>
    product.artwork.errors || product.tracks.some(track => track.errors);

const isUploadingFile = (
    filename: string | null | undefined,
    uploadingFilenames: string[]
) =>
    !!filename &&
    uploadingFilenames.some(
        name => name.normalize('NFC') === filename.normalize('NFC')
    );

const getTrackStatus = (product: Product) => {
    let status = ASSET_STATUS.Success;
    if (product.tracks.some(track => track.status == ASSET_STATUS.InProgress))
        status = ASSET_STATUS.InProgress;
    else if (product.tracks.some(track => track.errors))
        status = ASSET_STATUS.Fail;
    else if (product.tracks.some(track => track.status == ASSET_STATUS.Skipped))
        status = ASSET_STATUS.Skipped;
    return status;
};

const getArtworkStatus = (product: Product) => {
    if (
        product.artwork.status == ASSET_STATUS.Skipped &&
        product.artwork.errors
    )
        return ASSET_STATUS.Fail;
    return product.artwork.status;
};

interface AssetRow {
    productName: string;
    productCode: string;
    artworkStatus: ASSET_STATUS;
    trackStatus: ASSET_STATUS;
}

const ArtworkCell: FC<GridTableCellProps<AssetRow>> = ({ data }) => (
    <AssetReportStatus assetStatus={data.artworkStatus} />
);

const TrackCell: FC<GridTableCellProps<AssetRow>> = ({ data }) => (
    <AssetReportStatus assetStatus={data.trackStatus} />
);

const AssetReportTable = ({
    loading,
    products,
    pageNumber,
    pageSize,
    numProducts,
    onPageChange,
    onPageSizeChange,
    onSort,
    uploadingFilenames = [],
}: {
    loading: boolean;
    products: Product[] | null;
    pageNumber: number;
    pageSize: number;
    numProducts: number;
    onPageChange: (page: number) => void;
    onPageSizeChange: (size: number) => void;
    onSort: (sort: GridTableSortBy[]) => void;
    uploadingFilenames?: string[];
}) => {
    const [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set());

    const expandedRows: Record<string, FC> = useMemo(() => {
        const rows: Record<string, FC> = {};
        expandedKeys.forEach(code => {
            const product = products?.find(p => p.productCode === code);
            rows[code] = () =>
                product && hasErrors(product) ? (
                    <AssetReportErrors product={product} />
                ) : null;
        });
        return rows;
    }, [expandedKeys, products]);

    const data: AssetRow[] | undefined = products?.map(p => ({
        productName: p.productName,
        productCode: p.productCode,
        artworkStatus: isUploadingFile(p.artwork.filename, uploadingFilenames)
            ? ASSET_STATUS.InProgress
            : getArtworkStatus(p),
        trackStatus: p.tracks.some(track =>
            isUploadingFile(track.filename, uploadingFilenames)
        )
            ? ASSET_STATUS.InProgress
            : getTrackStatus(p),
    }));

    return (
        <GridTable
            variant="zebra"
            loading={loading}
            data={data}
            onRowClick={({ key }) =>
                setExpandedKeys(prev =>
                    prev.has(key) ? new Set() : new Set([key])
                )
            }
            expandedRows={expandedRows}
            rowKey="productCode"
            rowClassName={({ data: product }) =>
                product.artworkStatus == ASSET_STATUS.Fail ||
                product.trackStatus == ASSET_STATUS.Fail
                    ? 'error-row'
                    : 'unclickable'
            }
            paginated
            page={pageNumber}
            pageSize={pageSize}
            onPageChange={onPageChange}
            onPageSizeChange={onPageSizeChange}
            onSort={onSort}
            totalCount={numProducts}
            columnDefs={[
                {
                    name: 'productName',
                    title: $t('bulkDigitalAudio.assetReport.productName'),
                    Cell: ({ data: product }) => (
                        <div
                            className="truncated-cell"
                            title={product.productName ?? undefined}
                        >
                            {product.productName}
                        </div>
                    ),
                },
                {
                    name: 'productCode',
                    title: $t('bulkDigitalAudio.assetReport.productCode'),
                    Cell: ({ data: product }) => (
                        <div
                            className="truncated-cell"
                            title={product.productCode ?? undefined}
                        >
                            {product.productCode}
                        </div>
                    ),
                },
                {
                    name: 'ARTWORK',
                    title: $t('bulkDigitalAudio.assetReport.artwork'),
                    sortable: true,
                    Cell: ArtworkCell,
                },
                {
                    name: 'TRACK',
                    title: $t('bulkDigitalAudio.assetReport.track'),
                    sortable: true,
                    Cell: TrackCell,
                },
            ]}
        />
    );
};

export default AssetReportTable;
