import React, { useCallback, useEffect } from 'react';
import {
    Alert,
    Button,
    Control,
    Card,
    Field,
    Label as LabelField,
    Checkbox,
} from '@theorchard/suite-components';
import { formatMessage } from '@theorchard/suite-frontend';
import { GlyphIcon } from '@theorchard/suite-icons';
import { Link } from 'react-router-dom';
import { useLazyCheckSameTitleCompositionExistsQuery } from 'src/data/queries';
import { useDebounceCallback } from 'src/utils/debounce';
import { songUrl } from 'src/utils/urls';
import { titleError, iswcError, alternateError } from './errors';

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

interface Props {
    compositionId: string | null | undefined;
    title: string;
    iswc: string;
    alternateTitles: string[];
    setTitle: (title: string) => void;
    setIswc: (iswc: string) => void;
    setAlternateTitles: (alternateTitles: string[]) => void;
    containsPublicDomain: boolean;
    setContainsPublicDomain: (data: boolean) => void;
    containsSample: boolean;
    setContainsSample: (data: boolean) => void;
    showPubSongId: boolean;
    pubSongId?: number;
}

const Details: React.FC<Props> = ({
    compositionId,
    title,
    setTitle,
    alternateTitles,
    setAlternateTitles,
    iswc,
    setIswc,
    containsPublicDomain,
    setContainsPublicDomain,
    containsSample,
    setContainsSample,
    showPubSongId,
    pubSongId,
}) => {
    const addAlternateTitle = () => {
        setAlternateTitles([...alternateTitles, '']);
    };

    const setAlternateTitle = (value: string, i: number) => {
        const newValues = [...alternateTitles];
        newValues[i] = value;
        setAlternateTitles(newValues);
    };

    const removeAlternateField = (i: number) => {
        const copy = [...alternateTitles];
        copy.splice(i, 1);
        setAlternateTitles(copy);
    };

    const [potentiallyDuplicateSongId, setPotentiallyDuplicateSongId] =
        React.useState<string>();
    const [checkSameTitleComposition] =
        useLazyCheckSameTitleCompositionExistsQuery(
            setPotentiallyDuplicateSongId
        );

    const querySameTitleSongExists = useCallback(
        (titleSearch: string) => {
            // Do not perform duplicates check when editing existing composition
            if (compositionId || !titleSearch) return;

            void checkSameTitleComposition({
                variables: {
                    filter: {
                        titleSearch,
                        titleSearchExact: true,
                    },
                    limit: 5,
                    offset: 0,
                },
            });
        },
        [checkSameTitleComposition, compositionId]
    );

    const querySameTitleSongExistsDebounced = useDebounceCallback(
        querySameTitleSongExists,
        500
    );

    useEffect(() => {
        setPotentiallyDuplicateSongId(undefined);
        void querySameTitleSongExistsDebounced(title);
    }, [title, querySameTitleSongExistsDebounced]);

    useEffect(() => {
        setPotentiallyDuplicateSongId(potentiallyDuplicateSongId);
    }, [potentiallyDuplicateSongId]);

    return (
        <Card suite className="NewSong-details">
            <div className="NewSong-header">
                <div className="NewSong-header-title">
                    {formatMessage('newSong.details')}
                </div>
            </div>

            <Field
                controlId="mainTitle"
                labelText={formatMessage('newSong.songTitle')}
                errorMessage={titleError(title)}
            >
                <input
                    type="text"
                    id="mainTitle"
                    value={title}
                    placeholder={formatMessage('newSong.songTitlePlaceholder')}
                    onChange={e => setTitle(e.target.value)}
                    className="form-control"
                />
            </Field>

            {potentiallyDuplicateSongId && (
                <Alert
                    variant="warn"
                    text={
                        <div className="d-flex align-items-center justify-content-between">
                            <span>
                                {formatMessage('newSong.sameTitleSongExists')}
                            </span>
                            <LinkAny to={songUrl(potentiallyDuplicateSongId)}>
                                <Button
                                    data-testid="editUserAccess"
                                    variant="link"
                                    size="sm"
                                >
                                    {formatMessage('newSong.goToSong')}
                                    <GlyphIcon name="arrowRight" size={12} />
                                </Button>
                            </LinkAny>
                        </div>
                    }
                />
            )}

            {alternateTitles.map((alternateTitle, i) => (
                <Control
                    errorMessage={alternateError(alternateTitle)}
                    key={i}
                    className="NewSong-alternate-field-control"
                >
                    <div className="NewSong-alternate-field">
                        <input
                            type="text"
                            value={alternateTitle}
                            placeholder={formatMessage(
                                'newSong.alternateSongTitlePlaceholder'
                            )}
                            onChange={e => setAlternateTitle(e.target.value, i)}
                            className="form-control"
                        />
                        <div
                            className="NewSong-alternate-field-x"
                            onClick={() => removeAlternateField(i)}
                        >
                            <GlyphIcon name="close" size={16} />
                        </div>
                    </div>
                </Control>
            ))}

            <Button
                variant="link"
                className="icon-left"
                onClick={addAlternateTitle}
            >
                <GlyphIcon name="plus" size={16} />
                {formatMessage('newSong.addAlternateSong')}
            </Button>

            {showPubSongId && pubSongId && (
                <Field
                    controlId="songId"
                    labelText={formatMessage('generic.songId')}
                >
                    <input
                        type="number"
                        id="songId"
                        value={pubSongId}
                        placeholder={formatMessage('generic.optional')}
                        disabled
                        className="form-control"
                    />
                </Field>
            )}

            <Field
                controlId="iswc"
                labelText={formatMessage('generic.iswc')}
                errorMessage={iswcError(iswc)}
            >
                <input
                    type="text"
                    value={iswc}
                    id="iswc"
                    placeholder={formatMessage('generic.optional')}
                    onChange={e => setIswc(e.target.value)}
                    className="form-control"
                />
            </Field>

            <div>
                <LabelField
                    text={formatMessage('newSong.songContainsElements')}
                />
                <Checkbox
                    id={`pub_domain_${compositionId}`}
                    className="NewSong-publicDomain"
                    label={formatMessage('generic.publicDomain')}
                    checked={containsPublicDomain}
                    onChange={({ target }) =>
                        setContainsPublicDomain(target.checked)
                    }
                />
                <Checkbox
                    id={`sampling_${compositionId}`}
                    className="NewSong-sampling"
                    label={formatMessage('generic.sampling')}
                    checked={containsSample}
                    onChange={({ target }) => setContainsSample(target.checked)}
                />
            </div>
        </Card>
    );
};

export default Details;
