import { N_A_AUDIO_ATTRIBUTE_ID, N_A_RIGHTS_ATTRIBUTE_ID } from 'src/constants';
import type {
    UpsertTrackAudioAttributeInput,
    UpsertTrackRightsAttributeInput,
} from 'src/data/globalTypes';
import type { ProductTrack } from 'src/data/queries/product/types';
import type { ProductField } from 'src/product/fields/field';
import type { TrackMetadata } from 'src/product/track';

// Copy a track's reviewer edits onto its attribute value. Replicate when the
// reviewer made a real selection (non-empty), or when they deliberately
// cleared it (revised to empty, which resolves to N/A on Approve). An
// untouched empty edits array is left alone so the suggestion-seeded value set
// in the TrackMetadata constructor survives.
const replicateAttributesFromEdits = <T,>(
    editsField: ProductField<T>,
    attributesField: ProductField<T>
) => {
    const edits = editsField.get();
    if (Array.isArray(edits) && (edits.length || editsField.isRevised))
        attributesField.setCurrent(edits);
};

export const clearTrackAudioAttributesEdits = (
    mergedProductTracks: TrackMetadata[] | undefined
) => {
    mergedProductTracks?.forEach(track =>
        track.audioAttributesEdits.setCurrent([])
    );
};

export const clearTrackRightsAttributesEdits = (
    mergedProductTracks: TrackMetadata[] | undefined
) => {
    mergedProductTracks?.forEach(track =>
        track.rightsAttributesEdits.setCurrent([])
    );
};

export const replicateTrackAudioAttributesFromEdits = (
    mergedProductTracks: TrackMetadata[] | undefined
) => {
    mergedProductTracks?.forEach(track =>
        replicateAttributesFromEdits(
            track.audioAttributesEdits,
            track.audioAttributes
        )
    );
};

export const replicateTrackRightsAttributesFromEdits = (
    mergedProductTracks: TrackMetadata[] | undefined
) => {
    mergedProductTracks?.forEach(track =>
        replicateAttributesFromEdits(
            track.rightsAttributesEdits,
            track.rightsAttributes
        )
    );
};

export const isMissingTrackAttributes = (
    mergedProductTracks: TrackMetadata[] | undefined,
    productTracks: ProductTrack[]
): {
    foundMissingAudioAttributes: boolean;
    foundMissingRightsAttributes: boolean;
} => {
    let foundMissingAudioAttributes;
    let foundMissingRightsAttributes;
    if (mergedProductTracks) {
        foundMissingAudioAttributes = mergedProductTracks.some(t => {
            const audioAttributes = t.audioAttributes.get();
            return Array.isArray(audioAttributes) && !audioAttributes.length;
        });
        foundMissingRightsAttributes = mergedProductTracks.some(t => {
            const rightsAttributes = t.rightsAttributes.get();
            return Array.isArray(rightsAttributes) && !rightsAttributes.length;
        });
    } else {
        foundMissingAudioAttributes = productTracks.some(
            t => !t.audioAttributes.length
        );
        foundMissingRightsAttributes = productTracks.some(
            t => !t.rightsAttributes.length
        );
    }
    return {
        foundMissingAudioAttributes,
        foundMissingRightsAttributes,
    };
};

export const getAudioAttributes = (
    mergedProductTracks: TrackMetadata[] | undefined,
    productTracks: ProductTrack[]
): UpsertTrackAudioAttributeInput[] => {
    if (mergedProductTracks) {
        return mergedProductTracks.map(t => {
            const audioAttributes = t.audioAttributes.get();

            return {
                tuid: t.tuid.toString(),
                audioAttributeIds: Array.isArray(audioAttributes)
                    ? audioAttributes.map(aa => aa.attribute.id)
                    : [],
            };
        });
    }
    return productTracks.map(t => {
        return {
            tuid: t.tuid,
            audioAttributeIds: t.audioAttributes.map(aa => aa.attribute.id),
        };
    });
};

export const getRightsAttributes = (
    mergedProductTracks: TrackMetadata[] | undefined,
    productTracks: ProductTrack[]
): UpsertTrackRightsAttributeInput[] => {
    if (mergedProductTracks) {
        return mergedProductTracks.map(t => {
            const rightsAttributes = t.rightsAttributes.get();

            return {
                tuid: t.tuid.toString(),
                rightsAttributeIds: Array.isArray(rightsAttributes)
                    ? rightsAttributes.map(aa => aa.attribute.id)
                    : [],
            };
        });
    }
    return productTracks.map(t => {
        return {
            tuid: t.tuid,
            rightsAttributeIds: t.rightsAttributes.map(aa => aa.attribute.id),
        };
    });
};

export const getAudioAttributesInput = (
    mergedProductTracks: TrackMetadata[] | undefined,
    productTracks: ProductTrack[]
): UpsertTrackAudioAttributeInput[] => {
    if (mergedProductTracks) {
        return mergedProductTracks.map(t => {
            const audioAttributes = t.audioAttributes.get();
            if (!Array.isArray(audioAttributes) || !audioAttributes.length) {
                return {
                    tuid: t.tuid.toString(),
                    audioAttributeIds: [N_A_AUDIO_ATTRIBUTE_ID],
                };
            }

            return {
                tuid: t.tuid.toString(),
                audioAttributeIds: audioAttributes.map(aa => aa.attribute.id),
            };
        });
    }
    return productTracks.map(t => {
        if (!t.audioAttributes.length) {
            return {
                tuid: t.tuid,
                audioAttributeIds: [N_A_AUDIO_ATTRIBUTE_ID],
            };
        }

        return {
            tuid: t.tuid,
            audioAttributeIds: t.audioAttributes.map(aa => aa.attribute.id),
        };
    });
};

export const getRightsAttributesInput = (
    mergedProductTracks: TrackMetadata[] | undefined,
    productTracks: ProductTrack[]
): UpsertTrackRightsAttributeInput[] => {
    if (mergedProductTracks) {
        return mergedProductTracks.map(t => {
            const rightsAttributes = t.rightsAttributes.get();
            if (!Array.isArray(rightsAttributes) || !rightsAttributes.length) {
                return {
                    tuid: t.tuid.toString(),
                    rightsAttributeIds: [N_A_RIGHTS_ATTRIBUTE_ID],
                };
            }

            return {
                tuid: t.tuid.toString(),
                rightsAttributeIds: rightsAttributes.map(ra => ra.attribute.id),
            };
        });
    }

    return productTracks.map(t => {
        if (!t.rightsAttributes.length) {
            return {
                tuid: t.tuid,
                rightsAttributeIds: [N_A_RIGHTS_ATTRIBUTE_ID],
            };
        }
        return {
            tuid: t.tuid,
            rightsAttributeIds: t.rightsAttributes.map(ra => ra.attribute.id),
        };
    });
};
