import {
    type RecursiveRecord
} from "../../types";

const mergeCurrent = (defaultJSON: RecursiveRecord, projectJSON: RecursiveRecord) => {
    const projectKeys: Array<keyof typeof projectJSON> = Object.keys(projectJSON);

    const newJSON = JSON.parse(JSON.stringify(defaultJSON));

    projectKeys.forEach((pKey) => {
        const pValue = projectJSON[pKey];
        const dValue = defaultJSON[pKey];

        if(typeof pValue === "string") {
            newJSON[pKey] = pValue;
        } else {
            if(typeof dValue !== "string") {
                if(dValue) {
                    newJSON[pKey] = mergeCurrent(dValue, pValue as RecursiveRecord);
                } else {
                    newJSON[pKey] = pValue;
                }
            } else {
                newJSON[pKey] = dValue;
            }
        }
    });

    return newJSON;
};

export const mergeTheme = (
    defaultTheme: NCoreUIKit.ThemeTokens,
    projectTheme: NCoreUIKit.ThemeTokens
): NCoreUIKit.ThemeTokens => {
    return {
        content: mergeCurrent(defaultTheme.content as unknown as RecursiveRecord, projectTheme.content as unknown as RecursiveRecord),
        project: mergeCurrent(defaultTheme.project as unknown as RecursiveRecord, projectTheme.project as unknown as RecursiveRecord),
        system: mergeCurrent(defaultTheme.system as unknown as RecursiveRecord, projectTheme.system as unknown as RecursiveRecord),
        code: mergeCurrent(defaultTheme.code as unknown as RecursiveRecord, projectTheme.code as unknown as RecursiveRecord)
    };
};

export const mergePalettes = (
    defaultPalettes: NCoreUIKit.ThemePalettes,
    projectPalettes: NCoreUIKit.ThemePalettes,
    activePalette: keyof NCoreUIKit.PaletteKey,
    activeTheme: keyof NCoreUIKit.ThemeKey
): NCoreUIKit.ThemeTokens => {
    const defaultPalette = defaultPalettes.find(p => p.name === activePalette);

    if(!defaultPalette) {
        const projectPalette = projectPalettes.find(p => p.name === activePalette);

        if(projectPalette) {
            const projectThemeKey = Object.keys(projectPalette.themes).find(t => t === activeTheme) as keyof typeof projectPalette.themes;

            if(projectThemeKey) {
                const projectTheme = projectPalette.themes[projectThemeKey] as unknown as NCoreUIKit.ThemeTokens;

                return projectTheme;
            }

            return Object.values(projectPalette.themes)[0] as unknown as NCoreUIKit.ThemeTokens;
        } else {
            const fallbackP = defaultPalettes[0]!;
            return (fallbackP.themes.dark ?? Object.values(fallbackP.themes)[0]) as unknown as NCoreUIKit.ThemeTokens;
        }
    }

    const projectPalette = projectPalettes.find(p => p.name === activePalette);

    if(projectPalette) {
        const defaultThemeKey = Object.keys(defaultPalette.themes).find(t => t === activeTheme) as keyof typeof defaultPalette.themes;
        let defaultTheme = defaultPalette.themes[defaultThemeKey];

        if(!defaultTheme) {
            defaultTheme = defaultPalette.themes.dark ?? Object.values(defaultPalette.themes)[0];
        }

        const projectThemeKey = Object.keys(projectPalette.themes).find(t => t === activeTheme) as keyof typeof projectPalette.themes;

        if(projectThemeKey) {
            const projectTheme = projectPalette.themes[projectThemeKey] as unknown as NCoreUIKit.ThemeTokens;

            return mergeTheme(defaultTheme as unknown as NCoreUIKit.ThemeTokens, projectTheme);
        }

        return defaultTheme as unknown as NCoreUIKit.ThemeTokens;
    }

    const defaultThemeKey = Object.keys(defaultPalette.themes).find(t => t === activeTheme) as keyof typeof defaultPalette.themes;
    let activeT = defaultPalette.themes[defaultThemeKey];

    if(!activeT) {
        activeT = defaultPalette.themes.dark ?? Object.values(defaultPalette.themes)[0];
    }

    return activeT as unknown as NCoreUIKit.ThemeTokens;
};
