import React, { useState } from 'react';
import {
    Pill,
    TruncatedText,
    useFullscreenModal,
    GridTable,
} from '@theorchard/suite-components';
import { formatMessage } from '@theorchard/suite-frontend';
import { GlyphIcon } from '@theorchard/suite-icons';
import { groupBy, uniqWith, isEqual } from 'lodash';
import { Link, useHistory } from 'react-router-dom';
import NewSongwriterActions from 'src/pages/songWriterListPage/newSongwriterActions';
import { CLASSNAME } from 'src/pages/songWriterListPage/songWriters';
import { songUrl } from 'src/utils/urls';
import type { SongWriter } from 'src/types';

interface Props {
    songWriter: SongWriter;
    onSongWriterDelete: (songWriter: SongWriter) => void;
    fromPage: number;
}

type AgreementCompositions = SongWriter['agreements'][0]['compositions'];

const renderNotRegisteredCell = () => (
    <div className={`${CLASSNAME}-not-registered`}>
        <span>{formatMessage('generic.notRegistered')}</span>
        <GlyphIcon name="warning" size={16} />
    </div>
);

// Workaround for React 18 + react-router-dom v5 type incompatibility
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const LinkAny = Link as any;

const CompositionList: React.FC<{
    compositions?: AgreementCompositions;
}> = ({ compositions }) => (
    <div className={`${CLASSNAME}-link-list`}>
        <GridTable
            data={compositions}
            columnDefs={[
                {
                    name: 'title',
                    Cell: ({ data }) => (
                        <div>
                            <LinkAny to={songUrl(data.id)}>
                                {data.title}
                            </LinkAny>
                        </div>
                    ),
                },
            ]}
            hideColumnHeaders
            hideColumnSeparators
        />
    </div>
);

const renderAssociatedCompositionsCell = ({
    id,
    compositions,
    agreements,
}: SongWriter) => {
    const uniqueCompositions = uniqWith(
        compositions
            .map(composition =>
                agreements.map(agreement => {
                    if (
                        agreement.compositions.find(
                            c => c.id === composition.id
                        )
                    )
                        return {
                            id: composition.id,
                            title: composition.title,
                            controlled: agreement.controlled,
                            agreementId: agreement.id,
                        };
                })
            )
            .flat()
            .filter(i => i),
        isEqual
    );

    const grouped = groupBy(uniqueCompositions, 'controlled');

    const map: Map<string, AgreementCompositions> = Object.keys(grouped).reduce(
        (map, key) => {
            map.set(key, grouped[key]);
            return map;
        },
        new Map()
    );

    if (!map.get('true')?.length && !map.get('false')?.length)
        return <div className={`${CLASSNAME}-pill-zero`}>0</div>;

    return (
        <>
            {map.get('true') && (
                <Pill
                    className={`${CLASSNAME}-pill`}
                    text={`${map.get('true')?.length} ${formatMessage('generic.controlled')}`}
                    popoverOptions={{
                        id: `${id}-controlled`,
                        content: (
                            <CompositionList compositions={map.get('true')} />
                        ),
                    }}
                />
            )}

            {map.get('false') && (
                <Pill
                    className={`${CLASSNAME}-pill`}
                    text={`${map.get('false')?.length} ${formatMessage('generic.nonControlled')}`}
                    popoverOptions={{
                        id: `${id}-non-controlled`,
                        content: (
                            <CompositionList compositions={map.get('false')} />
                        ),
                    }}
                />
            )}
        </>
    );
};

const SongWriterRow: React.FC<Props> = ({
    songWriter,
    onSongWriterDelete,
    fromPage,
}) => {
    const { open: openFullScreenModal, close: closeFullScreenModal } =
        useFullscreenModal();
    const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
    const history = useHistory();

    const toggleFullscreenModal = () => {
        if (isModalOpen) {
            closeFullScreenModal(() => {
                setIsModalOpen(false);
            });
        } else {
            openFullScreenModal(() => {
                setIsModalOpen(true);
                history.push({
                    pathname: `/song-writer/${songWriter.id}`,
                    state: { songWriter, fromPage },
                });
            });
        }
    };

    return (
        <tr key={songWriter.id}>
            <td className={`${CLASSNAME}-legal-name-column`}>
                <div className="Songs-link">{songWriter.legalName}</div>
                <TruncatedText
                    className={`${CLASSNAME}-pka`}
                    text={songWriter.professionallyKnownAs.join(', ')}
                    maxWidth={280}
                />
            </td>
            <td>{songWriter.pro || renderNotRegisteredCell()}</td>
            <td>{songWriter.ipi || renderNotRegisteredCell()}</td>
            <td>{renderAssociatedCompositionsCell(songWriter)}</td>
            <td>
                <NewSongwriterActions
                    songWriter={songWriter}
                    onSongWriterEdit={toggleFullscreenModal}
                    onSongWriterDelete={onSongWriterDelete}
                />
            </td>
        </tr>
    );
};

export default SongWriterRow;
