import type { FC } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import { GridTable, Popover, Section } from '@theorchard/suite-components';
import { formatMessage } from '@theorchard/suite-frontend';
import { GlyphIcon } from '@theorchard/suite-icons';
import { useAudioInfringementModalContext } from 'src/components/audioInfringementModalProvider/audioInfringementModalProvider';
import TrackFieldValidation from 'src/components/trackFieldValidation/trackFieldValidation';
import { EMPTY_CHAR } from 'src/constants';
import {
    useDisplayAudioAttributesFF,
    useDisplayRightsAttributesFF,
    useTrackFocusTrackFF,
} from 'src/utils/features';
import { isClassicalGenre } from 'src/utils/product';
import { useTablePagination } from 'src/utils/useTablePagination';
import { filterValidations } from '../../utils/productValidation';
import PotentialAudioInfringementModal from '../potentialAudioInfringementModal/potentialAudioInfringementModal';
import ProductTrackAttributes from '../productTrackAttributes/productTrackAttributes';
import ProductTrackAttributesPopoverContent from '../productTrackAttributesPopoverContent/productTrackAttributesPopoverContent';
import ProductTrackRightsAttributes from '../productTrackRightsAttributes/productTrackRightsAttributes';
import ProductTrackAudioContainer from '../productTracksAudioContainer';
import ProductTracksFocusTrackTooltip from '../productTracksFocusTrackTooltip';
import ProductTracksCellData from '../productTracksTableRow/productTracksCellData';
import type { GridTableCellProps } from '@theorchard/suite-components';
import type { MergedProduct } from 'src/product/product';
import type { TrackMetadata } from 'src/product/track';
export const CLASS_NAME = 'ProductTracksTable';
export const INTL_PREFIX = 'contentReview.productTracksTable';

export interface Props {
    product: MergedProduct;
    isMergedProductFullyLoaded: boolean;
    currentTrackId: string;
    onChangeCurrentTrack: (a: string, b?: number) => void;
    onChangeAudioStatus: (value: number) => void;
    audioStatus: number;
}

const ProductTracksTable: FC<Props> = ({
    product,
    isMergedProductFullyLoaded,
    currentTrackId,
    onChangeCurrentTrack,
    onChangeAudioStatus,
    audioStatus,
}) => {
    const displayRightsAttributes = useDisplayRightsAttributesFF();
    const displayAudioAttributes = useDisplayAudioAttributesFF();
    const { state: modalState, dispatch: modalDispatch } =
        useAudioInfringementModalContext();
    const [selectedAttributesPopoverRow, setSelectedAttributesPopoverRow] =
        useState<TrackMetadata>();
    const { data: pageData, ...pagination } = useTablePagination<TrackMetadata>(
        product.getTrackList()
    );

    const closePopover = () => {
        setSelectedAttributesPopoverRow(undefined);
        initialOpenPopoverClick.current = true;
    };

    // The initial click on the rowActions button opens the popover, but
    // without this additional check, the click on the button itself is
    // registered as a click outside the popover, closing it again immediately.
    const initialOpenPopoverClick = useRef(true);

    useEffect(() => {
        const clickListenerEvent = (event: MouseEvent) => {
            const targetPopovers = document.querySelectorAll('.PopoverOverlay');
            let targetPopover = undefined;
            if (targetPopovers.length > 1) {
                // The Popover is wrapped around the GlyphIcon, which can get
                // rendered on a vertical overflow (although only one is visible at
                // the same time). Therefore the popover gets rendered twice as
                // well. We hide the unwanted popover.
                targetPopovers[0]?.setAttribute('hidden', 'true');
                targetPopover = targetPopovers[1];
            } else {
                targetPopover = targetPopovers[0];
            }
            let clickedPopover = false;
            const composedPath = event.composedPath();
            if (targetPopover) {
                clickedPopover = composedPath.includes(targetPopover);
            }
            if (
                !initialOpenPopoverClick.current &&
                selectedAttributesPopoverRow &&
                !clickedPopover
            ) {
                closePopover();
            } else {
                initialOpenPopoverClick.current = false;
            }
        };
        // Add click listener to doc to detect clicks outside of Popover
        if (selectedAttributesPopoverRow) {
            document.addEventListener('click', clickListenerEvent);
            return () =>
                document.removeEventListener('click', clickListenerEvent);
        }
    }, [selectedAttributesPopoverRow]);

    const getToolTip = () => {
        // Prevent tooltip to be displayed on hover over popover.
        if (selectedAttributesPopoverRow !== undefined) return undefined;
        if (isMergedProductFullyLoaded)
            return formatMessage(`${INTL_PREFIX}.editAudioAttributes`);
        return formatMessage(`${INTL_PREFIX}.loadingMessage`);
    };

    const TrackNumberCell = ({
        data: { trackNumber },
    }: GridTableCellProps<TrackMetadata>) => <span>{trackNumber.get()}</span>;

    const NoticesCell = ({
        data: {
            tuid,
            validations,
            nextTrackWithValidation,
            previousTrackWithValidation,
            trackName,
            contributors,
        },
    }: GridTableCellProps<TrackMetadata>) => {
        const filteredValidations = filterValidations(
            validations,
            tuid,
            trackName,
            contributors,
            product
        );

        return (
            <TrackFieldValidation
                validations={filteredValidations}
                tuid={tuid}
                nextTuid={nextTrackWithValidation}
                previousTuid={previousTrackWithValidation}
            />
        );
    };

    const TrackNameCell = ({
        data: { trackName, focusTrack, focusTrackStartDate, focusTrackEndDate },
    }: GridTableCellProps<TrackMetadata>) => (
        <div>
            {useTrackFocusTrackFF() ? (
                <span className="cell-trackName-inner">
                    <ProductTracksCellData
                        field={trackName}
                        trackingFieldName="Name"
                    />
                    {focusTrack && (
                        <ProductTracksFocusTrackTooltip
                            startDate={
                                focusTrackStartDate.get()
                                    ? String(focusTrackStartDate.get())
                                    : null
                            }
                            endDate={
                                focusTrackEndDate.get()
                                    ? String(focusTrackEndDate.get())
                                    : null
                            }
                        />
                    )}
                </span>
            ) : (
                <ProductTracksCellData
                    field={trackName}
                    trackingFieldName="Name"
                />
            )}
        </div>
    );

    const TrackAudioCell = ({
        data: { tuid, duration, trackNumber },
    }: GridTableCellProps<TrackMetadata>) => (
        <span className="cell-trackAudio-inner">
            <ProductTrackAudioContainer
                tuid={String(tuid)}
                trackNumber={trackNumber.get()}
                product={product}
                currentTrackId={currentTrackId}
                onChangeCurrentTrack={onChangeCurrentTrack}
                onChangeAudioStatus={onChangeAudioStatus}
                audioStatus={audioStatus}
            />
            <ProductTracksCellData field={duration} trackingFieldName="Audio" />
        </span>
    );

    const TrackVersionCell = ({
        data: { version },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTracksCellData field={version} trackingFieldName="Version" />
    );

    const TrackRightsAttributeCell = ({
        data: { ownershipRights, offerType },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTrackRightsAttributes
            ownershipRights={ownershipRights}
            offerType={offerType}
        />
    );

    const AudioAttributeCell = ({
        data: { audioAttributesEdits },
    }: GridTableCellProps<TrackMetadata>) => {
        return <ProductTrackAttributes attributes={audioAttributesEdits} />;
    };

    const RightsAttributeCell = ({
        data: { rightsAttributesEdits },
    }: GridTableCellProps<TrackMetadata>) => {
        return <ProductTrackAttributes attributes={rightsAttributesEdits} />;
    };

    const TrackIsrcCell = ({
        data: { isrc },
    }: GridTableCellProps<TrackMetadata>) => (
        <span>{isrc.get() || EMPTY_CHAR}</span>
    );

    const IsrcCountCell = ({
        data: { isrc, isrcReuseCount },
    }: GridTableCellProps<TrackMetadata>) => {
        const count = isrcReuseCount.get();
        const soundRecordingLink = `/search?term=${isrc.get()}`;
        return (
            <div>
                <a href={soundRecordingLink} target="_blank" rel="noreferrer">
                    <div className="isrcLink">
                        <span className="cell-isrc-inner">{count}</span>
                        <span className="cell-isrc-inner">
                            <GlyphIcon
                                name="externalLink"
                                size={12}
                                className="linkIcon"
                            />
                        </span>
                    </div>
                </a>
            </div>
        );
    };

    const OfferTypeCell = ({
        data: { offerType },
    }: GridTableCellProps<TrackMetadata>) => (
        <span>{offerType.get() || EMPTY_CHAR}</span>
    );

    const LyricsLanguageCell = ({
        data: { lyricsLanguage },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTracksCellData
            field={lyricsLanguage}
            trackingFieldName="Lyrics Language"
        />
    );

    const LyricsCell = ({
        data: { lyrics },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTracksCellData field={lyrics} trackingFieldName="Lyrics" />
    );

    const ExplicitContentCell = ({
        data: { explicit },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTracksCellData
            field={explicit}
            trackingFieldName="Explicit Content"
        />
    );

    const PLineCell = ({
        data: { pLine },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTracksCellData field={pLine} trackingFieldName="P-Line" />
    );

    const VolumeCell = ({
        data: { volumeNumber },
    }: GridTableCellProps<TrackMetadata>) => (
        <ProductTracksCellData
            field={volumeNumber}
            trackingFieldName="Volume"
        />
    );

    const RowActionsIcon = () => {
        if (isMergedProductFullyLoaded) {
            return (
                <Popover
                    id="attributesPopover"
                    show={selectedAttributesPopoverRow !== undefined}
                    content={
                        <ProductTrackAttributesPopoverContent
                            tracks={product.getTrackList()}
                            selectedRow={selectedAttributesPopoverRow}
                            close={closePopover}
                        />
                    }
                >
                    <GlyphIcon
                        name="review"
                        size={16}
                        className="PopoverOpenButton"
                    />
                </Popover>
            );
        } else {
            return <GlyphIcon name="inProgress" size={16} />;
        }
    };

    const itemsCountText =
        product.getTrackList().length <= 20
            ? `${product.getTrackList().length} ${$t(
                  'contentReview.productTracks.track(s)'
              )}`
            : undefined;

    return (
        <div className={CLASS_NAME} data-testid={CLASS_NAME}>
            <Section.Table>
                <GridTable
                    maxHeight="896px"
                    rowKey={row => `${row.tuid}`}
                    data={pageData}
                    bordered
                    stickyHeader
                    variant={'zebra'}
                    rowActions={
                        displayAudioAttributes
                            ? {
                                  rowActions: {
                                      condition: track =>
                                          selectedAttributesPopoverRow ===
                                              undefined ||
                                          track.tuid ===
                                              selectedAttributesPopoverRow.tuid,
                                      icon: <RowActionsIcon />,
                                      onClick: row => {
                                          if (
                                              isMergedProductFullyLoaded &&
                                              selectedAttributesPopoverRow ===
                                                  undefined
                                          ) {
                                              setSelectedAttributesPopoverRow(
                                                  row
                                              );
                                          }
                                      },
                                      tooltip: getToolTip(),
                                  },
                              }
                            : undefined
                    }
                    {...pagination}
                    paginationText={itemsCountText}
                >
                    <GridTable.Column
                        name="trackNumber"
                        title="#"
                        minWidth="2rem"
                        maxWidth="3rem"
                        align="center"
                        Cell={TrackNumberCell}
                    />
                    <GridTable.Column
                        name="notices"
                        title={$t(`${INTL_PREFIX}.notices`)}
                        minWidth="min-content"
                        align="center"
                        Cell={NoticesCell}
                    />
                    <GridTable.Column
                        name="trackAudio"
                        title={$t(`${INTL_PREFIX}.audio`)}
                        minWidth="min-content"
                        Cell={TrackAudioCell}
                    />
                    <GridTable.Column
                        name="trackName"
                        title={
                            isClassicalGenre(product)
                                ? $t(`${INTL_PREFIX}.workMovement`)
                                : $t(`${INTL_PREFIX}.trackName`)
                        }
                        minWidth="14rem"
                        Cell={TrackNameCell}
                    />
                    <GridTable.Column
                        name="trackVersion"
                        title={$t(`${INTL_PREFIX}.trackVersion`)}
                        minWidth="6rem"
                        Cell={TrackVersionCell}
                    />
                    {displayAudioAttributes && (
                        <GridTable.Column
                            name="audioAttribute"
                            title={$t(`${INTL_PREFIX}.audioAttribute`)}
                            minWidth="max-content"
                            Cell={AudioAttributeCell}
                        />
                    )}
                    {displayAudioAttributes && (
                        <GridTable.Column
                            name="rightsAttribute"
                            title={$t(`${INTL_PREFIX}.rightsAttribute`)}
                            minWidth="max-content"
                            Cell={RightsAttributeCell}
                        />
                    )}
                    {displayRightsAttributes && (
                        <GridTable.Column
                            name="trackRightsAttribute"
                            title={$t(`${INTL_PREFIX}.trackRights`)}
                            minWidth="9rem"
                            Cell={TrackRightsAttributeCell}
                        />
                    )}
                    <GridTable.Column
                        name="isrc"
                        title={$t(`${INTL_PREFIX}.isrc`)}
                        minWidth="min-content"
                        Cell={TrackIsrcCell}
                    />
                    <GridTable.Column
                        name="isrcCount"
                        title={$t(`${INTL_PREFIX}.isrcCount`)}
                        minWidth="min-content"
                        align="right"
                        Cell={IsrcCountCell}
                    />
                    <GridTable.Column
                        name="offerType"
                        title={$t(`${INTL_PREFIX}.offerType`)}
                        minWidth="5rem"
                        Cell={OfferTypeCell}
                    />
                    <GridTable.Column
                        name="volume"
                        title={$t(`${INTL_PREFIX}.volume`)}
                        minWidth="min-content"
                        Cell={VolumeCell}
                    />
                    <GridTable.Column
                        name="lyricsLanguage"
                        title={$t(`${INTL_PREFIX}.lyricsLanguage`)}
                        minWidth="8rem"
                        Cell={LyricsLanguageCell}
                    />
                    <GridTable.Column
                        name="trackLyrics"
                        title={$t(`${INTL_PREFIX}.trackLyrics`)}
                        minWidth="6rem"
                        Cell={LyricsCell}
                    />
                    <GridTable.Column
                        name="explicitContent"
                        title={$t(`${INTL_PREFIX}.explicitContent`)}
                        minWidth="6rem"
                        Cell={ExplicitContentCell}
                    />
                    <GridTable.Column
                        name="pLine"
                        title={$t(`${INTL_PREFIX}.pLine`)}
                        minWidth="7.5rem"
                        Cell={PLineCell}
                    />
                </GridTable>
                {modalState.data && (
                    <PotentialAudioInfringementModal
                        isOpen
                        onRequestClose={() => {
                            modalDispatch({
                                data: null,
                            });
                        }}
                        potentialAudioInfringementMatches={
                            modalState.data.potentialAudioInfringementMatches
                        }
                        crossAccountOSRConflictMatches={
                            modalState.data.crossAccountOSRConflictMatches
                        }
                        trackMetadata={modalState.data.trackMetadata}
                    />
                )}
            </Section.Table>
        </div>
    );
};

export default ProductTracksTable;
