import { searchAndReplace } from "@foxxmd/regex-buddy-core";
import type {ArtistCredit, PlayObject} from "../../../core/Atomic.ts";
import { configValToSearchReplace, isSearchAndReplaceTerm, isUserStage, testWhenConditions } from "../../utils/PlayTransformUtils.ts";
import type {WebhookPayload} from "../infrastructure/config/health/webhooks.ts";
import type {ConditionalSearchAndReplaceRegExp, PlayTransformUserStage} from "../../../core/Transform.ts";
import AtomicPartsTransformer from "./AtomicPartsTransformer.ts";

export default class UserTransformer extends AtomicPartsTransformer<ConditionalSearchAndReplaceRegExp[], undefined> {

    // protected constructor(config: TransformerCommon) {
    //     super(name, config);
    // }

    protected doParseConfig(data: PlayTransformUserStage<ConditionalSearchAndReplaceRegExp[]>) {
        if (!isUserStage(data)) {
            throw new Error(`UserTransformer is only usable with 'user' type stages`);
        }

        const {
            title = [],
            artists = [],
            album = [],
            albumArtists = [],
            ...rest
        } = data;

        const {
            defaults: {
                title: defTitle = [],
                artists: defArtist = [],
                album: defAlbum = [],
                albumArtists: defAA = [],
            } = {},
        } = this.config;

        const stage: PlayTransformUserStage<ConditionalSearchAndReplaceRegExp[]> = {
            ...rest,
            title: [...title, ...defTitle],
            artists: [...artists, ...defArtist],
            album: [...album, ...defAlbum],
            albumArtists: [...albumArtists, ...defAA],
            type: 'user'
        }

        for (const k of ['artists', 'title', 'album', 'albumArtists']) {
            if (!(k in stage)) {
                continue;
            }
            if (!Array.isArray(stage[k])) {
                throw new Error(`${k} must be an array`);
            }
            try {
                isSearchAndReplaceTerm(stage[k]);
                stage[k] = stage[k].map(configValToSearchReplace);
            } catch (e) {
                throw new Error(`Property '${k}' was not a valid type`, { cause: e });
            }
        }
        return stage;
    }

    protected generateMapper(play: PlayObject) {
        return (x: ConditionalSearchAndReplaceRegExp): ConditionalSearchAndReplaceRegExp => ({ ...x, test: (x.when !== undefined ? () => testWhenConditions(x.when, play, { testMaybeRegex: this.regex.testMaybeRegex }) : undefined) });
    }

    protected async handleTitle(play: PlayObject, parts: ConditionalSearchAndReplaceRegExp[], _transformData: undefined): Promise<string | undefined> {
        if (play.data.track === undefined) {
            return undefined;
        }
        const mapper = this.generateMapper(play);
        const result = searchAndReplace(play.data.track, parts.map(mapper));
        if(result.trim() === '') {
            return undefined;
        }
        return result.trim();
    }
    protected async handleArtists(play: PlayObject, parts: ConditionalSearchAndReplaceRegExp[], _transformData: undefined): Promise<ArtistCredit[] | undefined> {
        if(play.data.artists === undefined || play.data.artists.length === 0) {
            return play.data.artists;
        }
        const mapper = this.generateMapper(play);
        const transformedArtists = [];
        for(const artist of play.data.artists) {
            const a = searchAndReplace(artist.name, parts.map(mapper));
            if(a.trim() !== '') {
                transformedArtists.push({...artist, name: a});
            }
        }
        return transformedArtists;
    }
    protected async handleAlbumArtists(play: PlayObject, parts: ConditionalSearchAndReplaceRegExp[], _transformData: undefined): Promise<ArtistCredit[] | undefined> {
        if(play.data.albumArtists === undefined || play.data.albumArtists.length === 0) {
            return play.data.albumArtists;
        }
        const mapper = this.generateMapper(play);
        const transformedArtists = [];
        for(const artist of play.data.albumArtists) {
            const a = searchAndReplace(artist.name, parts.map(mapper));
            if(a.trim() !== '') {
                transformedArtists.push({...artist, name: a});
            }
        }
        return transformedArtists;
    }
    protected async handleAlbum(play: PlayObject, parts: ConditionalSearchAndReplaceRegExp[], _transformData: undefined): Promise<string | undefined> {
        if (play.data.album === undefined) {
            return undefined;
        }
        const mapper = this.generateMapper(play);
        const result = searchAndReplace(play.data.album, parts.map(mapper));
        if(result.trim() === '') {
            return undefined;
        }
        return result.trim();
    }

    public notify(payload: WebhookPayload): Promise<void> {
        return;
    }

}