import classNames from "classnames";
import {Color, ColorWithCustomTint} from "./Color";
import {colors, ConditionColorPalette, defaultConditionColorPalette, getColorForComponentType} from "./Colors";
import {
    applyConditionContextCardTheme,
    ConditionContextCardThemeClasses,
    conditionContextCardThemeOverridesByPlace,
    ConditionContextThemePlace,
    getConditionContextCardTheme
} from "./conditionCardTheme";

export type TierColorPlace = 'tier-base' | 'tier-subchild' | 'tier-branch' | 'tier-edge'

type TierComponentType = 'condition' | 'filter' | 'offer' | string

type TierComponentTypeOverride = {
    componentType: TierComponentType,
    conditionPalette?: ConditionColorPalette,
}

const normalizeKey = (value?: string): string | undefined => {
    if (!value) {
        return undefined
    }

    const normalizedValue = `${value}`.trim().toLowerCase()

    return normalizedValue || undefined
}

const tierConditionGraySource = colors.gray.color.intensity[20].source

const tierConditionGrayColor = new Color({
    ...colors.gray.color,
    intensity: {
        ...colors.gray.color.intensity,
        80: {
            ...colors.gray.color.intensity[80],
            source: tierConditionGraySource
        },
        100: {
            ...colors.gray.color.intensity[100],
            source: tierConditionGraySource
        }
    }
})

const tierConditionYellowColor = new Color({
    ...colors.conditionWashedmustard.color,
    intensity: {
        ...colors.conditionWashedmustard.color.intensity,
        80: {
            ...colors.conditionWashedmustard.color.intensity[60],
            source: colors.conditionWashedmustard.color.intensity[60].source
        },
        100: {
            ...colors.conditionWashedmustard.color.intensity[60],
            source: colors.conditionWashedmustard.color.intensity[60].source
        }
    }
})

export const getConditionPaletteFromNodeData = (
    nodeData?: unknown
): ConditionColorPalette | undefined => {
    if (
        nodeData
        && typeof nodeData === 'object'
        && 'conditionColorPalette' in nodeData
        && typeof nodeData.conditionColorPalette === 'string'
    ) {
        return nodeData.conditionColorPalette as ConditionColorPalette
    }

    return undefined
}

export const tierColorThemeConfig = {
    // How tier visuals should interpret incoming mode values.
    componentTypeByMode: {
        filter: 'filter',
        test: 'condition',
        condition: 'condition',
    } as Record<string, TierComponentType>,

    // Optional mapping by testableType.
    componentTypeByTestableType: {
        filter: 'filter',
        condition: 'condition',
    } as Record<string, TierComponentType>,

    // Fine-grained overrides by testableType.
    overridesByTestableType: {} as Partial<Record<string, TierComponentTypeOverride>>,

    // Centralized condition palette override for tiers.
    // Set `default` to force all tier condition/test colors at once.
    conditionPaletteByPlace: {
        default: undefined,
        'tier-base': undefined,
        'tier-subchild': undefined,
        'tier-branch': undefined,
        'tier-edge': undefined,
    } as Record<'default' | TierColorPlace, ConditionColorPalette | undefined>,

    // Optional full color override for tier condition/test visuals.
    // Useful for quickly testing non-palette colors (e.g. all gray).
    conditionColorOverrideByPlace: {
        default: colors.conditionYetanotherpurple,//colors.conditionYetanotherpurplishblue,
        /*'tier-base': colors.conditionWashedmustard,//colors.conditionWashedmustard,
        'tier-subchild': colors.conditionWashedmustard,//colors.conditionWashedmustard,
        'tier-branch': colors.conditionWashedmustard,//colors.conditionWashedmustard,
        'tier-edge': tierConditionYellowColor,//colors.conditionWashedmustard,*/
    } as Record<'default' | TierColorPlace, Color | undefined>,

    // Which condition-card theme place each tier color place should use.
    conditionThemePlaceByColorPlace: {
        'tier-base': 'tier-base',
        'tier-subchild': 'tier-subchild',
        'tier-branch': 'tier-base',
        'tier-edge': 'tier-subchild',
    } as Record<TierColorPlace, ConditionContextThemePlace>,
}

export const resolveTierComponentType = (options: {
    mode?: string,
    testableType?: string,
}): TierComponentType => {
    const normalizedTestableType = normalizeKey(options.testableType)

    if (normalizedTestableType) {
        const typeOverride = tierColorThemeConfig.overridesByTestableType[normalizedTestableType]

        if (typeOverride?.componentType) {
            return typeOverride.componentType
        }

        if (tierColorThemeConfig.componentTypeByTestableType[normalizedTestableType]) {
            return tierColorThemeConfig.componentTypeByTestableType[normalizedTestableType]
        }
    }

    const normalizedMode = normalizeKey(options.mode)

    if (normalizedMode && tierColorThemeConfig.componentTypeByMode[normalizedMode]) {
        return tierColorThemeConfig.componentTypeByMode[normalizedMode]
    }

    return 'filter'
}

export const resolveTierConditionPalette = (options: {
    place?: TierColorPlace,
    testableType?: string,
    inheritedConditionPalette?: ConditionColorPalette,
}): ConditionColorPalette => {
    const place = options.place || 'tier-base'
    const normalizedTestableType = normalizeKey(options.testableType)
    const paletteFromTestableType = normalizedTestableType
        ? tierColorThemeConfig.overridesByTestableType[normalizedTestableType]?.conditionPalette
        : undefined
    const paletteFromPlace = tierColorThemeConfig.conditionPaletteByPlace[place]
        || tierColorThemeConfig.conditionPaletteByPlace.default

    return (
        paletteFromTestableType
        || paletteFromPlace
        || options.inheritedConditionPalette
        || defaultConditionColorPalette
    )
}

const resolveTierConditionColorOverride = (place: TierColorPlace): Color | undefined => {
    return tierColorThemeConfig.conditionColorOverrideByPlace[place]
        || tierColorThemeConfig.conditionColorOverrideByPlace.default
}

const getConditionThemePlaceOverrides = (
    palette: ConditionColorPalette,
    place: ConditionContextThemePlace
): Partial<ConditionContextCardThemeClasses> => {
    const placeOverrides = conditionContextCardThemeOverridesByPlace[place]

    if (!placeOverrides) {
        return {}
    }

    return {
        ...(placeOverrides.default || {}),
        ...(placeOverrides[palette] || {}),
    }
}

const applyPartialConditionTheme = (
    color: Color | ColorWithCustomTint,
    overrides: Partial<ConditionContextCardThemeClasses>
): Color | ColorWithCustomTint => {
    if (Object.keys(overrides).length === 0) {
        return color
    }

    const baseColor = color instanceof Color ? color : color.color
    const inheritedTint = color instanceof Color ? undefined : color.tint

    return {
        color: baseColor,
        tint: (currentColor, type, context, path) => {
            const inheritedValue = inheritedTint?.(currentColor, type, context, path)

            if (inheritedValue) {
                return inheritedValue
            }

            switch (context) {
                case 'card-background':
                    if (type === 'get' && path === 'background.light' && overrides.background) {
                        return classNames(overrides.background, overrides.backgroundEffects)
                    }
                    break
                case 'card-background-active':
                    if (type === 'get' && path === 'background.extra' && overrides.activeBackground) {
                        return overrides.activeBackground
                    }
                    break
                case 'icon-background':
                    if (type === 'get' && path === 'background.dark' && overrides.iconBackground) {
                        return overrides.iconBackground
                    }
                    break
                case 'icon-color':
                    if (type === 'text' && overrides.iconColor) {
                        return overrides.iconColor
                    }
                    break
                case 'card-main-value':
                    if (type === 'get' && path === 'text.dark.primary' && overrides.mainValue) {
                        return overrides.mainValue
                    }
                    break
                case 'card-secondary-value':
                    if (type === 'get' && path === 'text.dark.secondary' && overrides.secondaryValue) {
                        return overrides.secondaryValue
                    }
                    break
            }

            if (type === 'get' && path === 'border.light.primary' && overrides.borderPrimary) {
                return overrides.borderPrimary
            }

            if (type === 'get' && path === 'border.light.secondary' && overrides.borderSecondary) {
                return overrides.borderSecondary
            }

            if (type === 'get' && path === 'background.dark' && overrides.connectorLine) {
                return overrides.connectorLine
            }

            return undefined
        }
    } as ColorWithCustomTint
}

export const getTierBaseColor = (options: {
    place?: TierColorPlace,
    mode?: string,
    testableType?: string,
    inheritedConditionPalette?: ConditionColorPalette,
}): Color => {
    const place = options.place || 'tier-base'
    const componentType = resolveTierComponentType({
        mode: options.mode,
        testableType: options.testableType,
    })

    if (componentType !== 'condition') {
        return getColorForComponentType(componentType)
    }

    const colorOverride = resolveTierConditionColorOverride(place)

    if (colorOverride) {
        return colorOverride
    }

    const conditionPalette = resolveTierConditionPalette({
        place,
        testableType: options.testableType,
        inheritedConditionPalette: options.inheritedConditionPalette,
    })

    return getColorForComponentType('condition', {conditionPalette})
}

export const getTierCardThemeColor = (options: {
    place?: TierColorPlace,
    mode?: string,
    testableType?: string,
    inheritedConditionPalette?: ConditionColorPalette,
}): Color | ColorWithCustomTint => {
    const place = options.place || 'tier-base'
    const componentType = resolveTierComponentType({
        mode: options.mode,
        testableType: options.testableType,
    })
    const baseColor = getTierBaseColor({
        place,
        mode: options.mode,
        testableType: options.testableType,
        inheritedConditionPalette: options.inheritedConditionPalette,
    })

    if (componentType !== 'condition') {
        return baseColor
    }

    const conditionPalette = resolveTierConditionPalette({
        place,
        testableType: options.testableType,
        inheritedConditionPalette: options.inheritedConditionPalette,
    })
    const conditionThemePlace = tierColorThemeConfig.conditionThemePlaceByColorPlace[place] || 'context'

    if (resolveTierConditionColorOverride(place)) {
        const conditionThemeOverrides = getConditionThemePlaceOverrides(conditionPalette, conditionThemePlace)

        return applyPartialConditionTheme(baseColor, conditionThemeOverrides)
    }

    const conditionTheme = getConditionContextCardTheme(conditionPalette, conditionThemePlace)

    return applyConditionContextCardTheme(baseColor, conditionTheme)
}
