import Konva from 'konva';
import type { ReactNode } from 'react';
import type { LayerStyle, Shadow } from '@/types/layout';

export type KonvaShadowProps = {
    shadowColor?: string;
    shadowBlur?: number;
    shadowOffsetX?: number;
    shadowOffsetY?: number;
    shadowOpacity?: number;
};

/**
 * Resolve a style's shadow state into a normalized array. `shadows` wins when
 * present; otherwise the legacy single `shadow` is wrapped. Empty array means
 * no shadow.
 */
export function resolveShadows(style: LayerStyle | undefined): Shadow[] {
    if (!style) return [];
    if (style.shadows && style.shadows.length > 0) return style.shadows;
    if (style.shadow) return [style.shadow];
    return [];
}

export function toKonvaShadowProps(shadow: Shadow | undefined): KonvaShadowProps {
    if (!shadow) return {};
    return {
        shadowColor: shadow.color,
        shadowBlur: shadow.blur,
        shadowOffsetX: shadow.offsetX,
        shadowOffsetY: shadow.offsetY,
        shadowOpacity: shadow.opacity,
    };
}

/**
 * React-side multi-shadow helper. For 0–1 shadows, delegates to `render` once.
 * For 2+ shadows, renders N copies in a Fragment: extras (listening off) below,
 * primary (listening on / ref target) on top. Callers own keying for extras.
 */
export function withShadows(
    shadows: Shadow[],
    render: (
        shadowProps: KonvaShadowProps,
        isPrimary: boolean,
        key: string | null,
    ) => ReactNode,
): ReactNode {
    if (shadows.length <= 1) {
        return render(toKonvaShadowProps(shadows[0]), true, null);
    }
    const extras = shadows.slice(0, -1);
    const primary = shadows[shadows.length - 1];
    return (
        <>
            {extras.map((s, i) =>
                render(toKonvaShadowProps(s), false, `extra-${i}`),
            )}
            {render(toKonvaShadowProps(primary), true, null)}
        </>
    );
}

/**
 * Imperative (export renderer) multi-shadow helper. Builds N copies and
 * attaches them to `parent` in order: extras first, primary last.
 */
export function addWithShadows(
    parent: Konva.Container,
    shadows: Shadow[],
    build: (shadowProps: KonvaShadowProps, isPrimary: boolean) => Konva.Node,
): void {
    if (shadows.length <= 1) {
        parent.add(build(toKonvaShadowProps(shadows[0]), true) as Konva.Group);
        return;
    }
    const extras = shadows.slice(0, -1);
    const primary = shadows[shadows.length - 1];
    for (const s of extras) {
        parent.add(build(toKonvaShadowProps(s), false) as Konva.Group);
    }
    parent.add(build(toKonvaShadowProps(primary), true) as Konva.Group);
}
