<template>
  <div
    class="z-[1] select-none touch-none"
    :class="[
      selected ? 'outline outline-2 outline-accent outline-offset-2' : '',
      isLabel ? 'px-1.5 py-1 rounded-md overflow-hidden whitespace-nowrap' : ''
    ]"
    :style="computedStyle"
    @mousedown.stop="!isTabPage && $emit('drag-start', { id: widget.id, event: $event })"
    @touchstart.stop="!isTabPage && $emit('drag-start', { id: widget.id, event: $event })"
    @click.stop="handleWidgetClick"
  >
    <!-- Recursive Children -->
    <!-- Special handling for TabView to render structure -->
    <template v-if="isTabView">
        <div class="flex w-full h-full overflow-hidden" :style="tabViewStyle">
            <div class="flex overflow-hidden bg-black/20" :style="tabBtnsStyle">
                <div 
                    v-for="(child, idx) in children" 
                    :key="child.id"
                    :class="tabBtnClass(activePageId === child.id)"
                    @click.stop="activeTabIndex = idx; store.selectedWidgetId = child.id"
                >
                    {{ child.text }}
                </div>
            </div>
            <div class="flex-1 relative overflow-hidden">
                <WidgetElement 
                    v-for="child in children" 
                    :key="child.id" 
                    :widget="child"
                    :scale="scale"
                    :selected="store.selectedWidgetId === child.id"
                    :style="{ display: activePageId === child.id ? 'block' : 'none' }"
                    @select="store.selectedWidgetId = child.id"
                    @drag-start="$emit('drag-start', $event)"
                    @resize-start="$emit('resize-start', $event)"
                />
            </div>
        </div>
    </template>

    <template v-else-if="isPowerFlow">
        <div class="absolute inset-0" :style="powerFlowBgStyle"></div>
        <div v-if="widget.text" class="absolute left-4 top-3 text-[13px] uppercase tracking-[0.08em]" :style="{ color: widget.textColor }">
            {{ widget.text }}
        </div>
        <svg class="absolute inset-0 pointer-events-none" :width="widget.w * scale" :height="widget.h * scale">
            <path
                v-for="link in powerFlowLinks"
                :key="`link-${link.id}`"
                :d="link.path"
                :stroke="link.color"
                :stroke-width="link.width"
                stroke-linecap="round"
                fill="none"
                :opacity="link.opacity"
            />
            <circle
                v-for="link in powerFlowLinks"
                :key="`dot-${link.id}`"
                :r="link.dotRadius"
                :fill="link.color"
                :opacity="link.opacity"
            >
                <animateMotion
                    :dur="`${link.duration}s`"
                    repeatCount="indefinite"
                    :path="link.path"
                />
            </circle>
        </svg>
        <div v-if="!powerNodes.length" class="absolute inset-0 grid place-items-center text-[12px] text-muted">
            Power Nodes hinzufuegen
        </div>
        <WidgetElement 
            v-for="child in powerFlowChildren" 
            :key="child.id" 
            :widget="child"
            :scale="scale"
            :selected="store.selectedWidgetId === child.id"
            @select="store.selectedWidgetId = child.id"
            @drag-start="$emit('drag-start', $event)"
            @resize-start="$emit('resize-start', $event)"
        />
    </template>
    
    <!-- Standard Recursive Children (for Buttons, Pages, etc) -->
    <template v-else>
        <WidgetElement 
            v-for="child in children" 
            :key="child.id" 
            :widget="child"
            :scale="scale"
            :selected="store.selectedWidgetId === child.id"
            @select="store.selectedWidgetId = child.id"
            @drag-start="$emit('drag-start', $event)"
            @resize-start="$emit('resize-start', $event)"
        />
    </template>

    <!-- Power Node Widget -->
    <template v-if="isPowerNode">
      <div class="flex flex-col items-center justify-center w-full h-full text-center leading-tight">
        <span v-if="powerNodeParts.label" :style="powerNodeLabelStyle">{{ powerNodeParts.label }}</span>
        <span v-if="widget.iconCodepoint" class="material-symbols-outlined mt-1" :style="powerNodeIconStyle">
          {{ iconChar }}
        </span>
        <span v-if="powerNodeParts.value" class="mt-1" :style="powerNodeValueStyle">{{ powerNodeParts.value }}</span>
      </div>
    </template>

    <template v-else-if="isChart">
      <div class="w-full h-full flex flex-col gap-2">
        <div class="text-[11px] uppercase tracking-[0.12em] opacity-80">
          {{ widget.text || 'Chart' }}
        </div>
        <div class="flex-1 rounded-[10px] bg-black/20 relative overflow-hidden">
          <div class="absolute inset-0 opacity-30" style="background-image: linear-gradient(to right, rgba(255,255,255,0.1) 1px, transparent 1px), linear-gradient(to bottom, rgba(255,255,255,0.1) 1px, transparent 1px); background-size: 24px 24px;"></div>
          <svg class="absolute inset-0" viewBox="0 0 100 40" preserveAspectRatio="none">
            <path d="M0,30 L15,22 L30,26 L45,14 L60,18 L75,10 L100,16" fill="none" stroke="rgba(239,99,81,0.8)" stroke-width="2" />
            <path d="M0,34 L20,28 L40,32 L60,20 L80,24 L100,18" fill="none" stroke="rgba(125,211,176,0.8)" stroke-width="2" />
          </svg>
        </div>
      </div>
    </template>

    <!-- Icon-only Widget -->
    <template v-else-if="isIcon">
      <span class="material-symbols-outlined flex items-center justify-center" :style="iconOnlyStyle">
        {{ iconChar }}
      </span>
    </template>

    <!-- Label/Button with Icon -->
    <template v-else-if="hasIcon">
      <div :style="contentStyle">
        <span
          v-if="iconPosition === 0 || iconPosition === 2"
          class="material-symbols-outlined flex-shrink-0"
          :style="iconStyle"
        >{{ iconChar }}</span>
        <span class="flex-shrink-0">{{ widget.text }}</span>
        <span
          v-if="iconPosition === 1 || iconPosition === 3"
          class="material-symbols-outlined flex-shrink-0"
          :style="iconStyle"
        >{{ iconChar }}</span>
      </div>
    </template>

    <!-- Standard (no icon) -->
    <template v-else>
      <span v-if="showDefaultText">{{ widget.text }}</span>
    </template>

    <!-- Resize Handle (at end to be on top) -->
    <div
        v-if="selected"
        class="absolute -right-1.5 -bottom-1.5 w-3.5 h-3.5 rounded-[4px] bg-accent border-[2px] border-[#1b1308] shadow-[0_4px_12px_rgba(0,0,0,0.35)] cursor-se-resize z-10"
        data-resize-handle
        @mousedown.stop="$emit('resize-start', { id: widget.id, event: $event })"
        @touchstart.stop="$emit('resize-start', { id: widget.id, event: $event })"
    >
        <span class="absolute right-[2px] bottom-[2px] w-[6px] h-[6px] border-r-2 border-b-2 border-[#1b1308a6] rounded-[2px]"></span>
    </div>
  </div>
</template>

<script setup>
import { computed, ref } from 'vue';
import { useEditorStore } from '../stores/editor';
import { WIDGET_TYPES, fontSizes, ICON_POSITIONS } from '../constants';
import { clamp, hexToRgba } from '../utils';

const props = defineProps({
    widget: { type: Object, required: true },
    scale: { type: Number, default: 1 },
    selected: { type: Boolean, default: false }
});

const emit = defineEmits(['select', 'drag-start', 'resize-start']);

const store = useEditorStore();

const children = computed(() => {
    if (!store.activeScreen) return [];
    return store.activeScreen.widgets.filter(w => w.parentId === props.widget.id);
});

const isLabel = computed(() => props.widget.type === WIDGET_TYPES.LABEL);
const isButton = computed(() => props.widget.type === WIDGET_TYPES.BUTTON);
const isLed = computed(() => props.widget.type === WIDGET_TYPES.LED);
const isIcon = computed(() => props.widget.type === WIDGET_TYPES.ICON);
const isTabView = computed(() => props.widget.type === WIDGET_TYPES.TABVIEW);
const isTabPage = computed(() => props.widget.type === WIDGET_TYPES.TABPAGE);
const isButtonContainer = computed(() => isButton.value && props.widget.isContainer);
const isPowerFlow = computed(() => props.widget.type === WIDGET_TYPES.POWERFLOW);
const isPowerNode = computed(() => props.widget.type === WIDGET_TYPES.POWERNODE);
const isPowerLink = computed(() => props.widget.type === WIDGET_TYPES.POWERLINK);
const isChart = computed(() => props.widget.type === WIDGET_TYPES.CHART);

const tabPosition = computed(() => props.widget.iconPosition || 0); // 0=Top, 1=Bottom...
const tabHeight = computed(() => (props.widget.iconSize || 5) * 10);

// Find active tab index (client-side state only, maybe store in widget temporarily?)
// For designer simplicity: show all tabs content stacked, or just first one?
// Better: mimic LVGL. We need state. Let's use a local ref or just show the selected one in tree?
// To keep it simple: Show the active tab based on which child is selected or default to first.
const activeTabIndex = ref(0);

const activePageId = computed(() => {
    // If a child page is selected, make it active
    const selectedChild = children.value.find(c => store.selectedWidgetId === c.id);
    if (selectedChild) return selectedChild.id;
    
    // If a widget inside a page is selected
    if (store.selectedWidget && store.selectedWidget.parentId !== -1) {
        // Find ancestor page
        let curr = store.selectedWidget;
        while (curr && curr.parentId !== -1 && curr.parentId !== props.widget.id) {
             curr = store.activeScreen.widgets.find(w => w.id === curr.parentId);
        }
        if (curr && curr.parentId === props.widget.id) return curr.id;
    }

    if (children.value.length > 0) return children.value[activeTabIndex.value]?.id;
    return -1;
});

const hasIcon = computed(() => {
    if (isButtonContainer.value) return false;
    return (isLabel.value || isButton.value) && props.widget.iconCodepoint > 0;
});

const iconChar = computed(() => {
    const cp = props.widget.iconCodepoint || 0xe88a;
    return String.fromCodePoint(cp);
});

const iconPosition = computed(() => props.widget.iconPosition || 0);
const textAlign = computed(() => props.widget.textAlign ?? 1);

const showDefaultText = computed(() => {
    if (isTabView.value || isTabPage.value) return false;
    if (isPowerFlow.value || isPowerNode.value) return false;
    if (isPowerLink.value) return false;
    if (isButtonContainer.value) return false;
    return true;
});

const justifyForAlign = (align) => {
    if (align === 0) return 'flex-start';
    if (align === 2) return 'flex-end';
    return 'center';
};

const textAlignCss = (align) => {
    if (align === 0) return 'left';
    if (align === 2) return 'right';
    return 'center';
};

const contentJustify = computed(() => {
    if (isButton.value || isLabel.value) return justifyForAlign(textAlign.value);
    return 'center';
});

const isVerticalLayout = computed(() => {
    return iconPosition.value === ICON_POSITIONS.TOP || iconPosition.value === ICON_POSITIONS.BOTTOM;
});

const contentStyle = computed(() => {
    const s = props.scale;
    const gap = (props.widget.iconGap || 8) * s;
    return {
        display: 'flex',
        flexDirection: isVerticalLayout.value ? 'column' : 'row',
        alignItems: 'center',
        justifyContent: contentJustify.value,
        gap: `${gap}px`,
        width: '100%',
        height: '100%'
    };
});

const iconStyle = computed(() => {
    const s = props.scale;
    const sizeIdx = props.widget.iconSize ?? props.widget.fontSize ?? 1;
    const size = fontSizes[sizeIdx] || 18;
    return {
        fontSize: `${size * s}px`,
        color: props.widget.textColor
    };
});

const iconOnlyStyle = computed(() => {
    const s = props.scale;
    const sizeIdx = props.widget.iconSize ?? 3;
    const size = fontSizes[sizeIdx] || 28;
    return {
        fontSize: `${size * s}px`,
        color: props.widget.textColor
    };
});

const powerNodeParts = computed(() => splitPowerNodeText(props.widget.text));

const powerNodeValueSize = computed(() => {
    const sizeIdx = props.widget.fontSize ?? 2;
    const size = fontSizes[sizeIdx] || 22;
    return size * props.scale;
});

const powerNodeLabelSize = computed(() => {
    return Math.max(10 * props.scale, powerNodeValueSize.value * 0.55);
});

const powerNodeIconSize = computed(() => {
    const sizeIdx = props.widget.iconSize ?? props.widget.fontSize ?? 2;
    const size = fontSizes[sizeIdx] || 22;
    return size * props.scale;
});

const powerNodeIconStyle = computed(() => ({
    fontSize: `${powerNodeIconSize.value}px`,
    color: props.widget.textColor
}));

const powerNodeLabelStyle = computed(() => ({
    fontSize: `${powerNodeLabelSize.value}px`,
    color: hexToRgba(props.widget.textColor, 0.72)
}));

const powerNodeValueStyle = computed(() => ({
    fontSize: `${powerNodeValueSize.value}px`,
    color: props.widget.textColor,
    fontWeight: '600'
}));

const powerNodes = computed(() => {
    if (!isPowerFlow.value) return [];
    return children.value.filter((child) => child.type === WIDGET_TYPES.POWERNODE && child.visible !== false);
});

const powerLinkWidgets = computed(() => {
    if (!isPowerFlow.value) return [];
    return children.value.filter((child) => child.type === WIDGET_TYPES.POWERLINK && child.visible !== false);
});

const powerFlowChildren = computed(() => {
    if (!isPowerFlow.value) return [];
    return children.value.filter((child) => child.type !== WIDGET_TYPES.POWERLINK);
});

const powerFlowLinks = computed(() => {
    if (!isPowerFlow.value || powerNodes.value.length < 2 || !powerLinkWidgets.value.length) return [];

    const s = props.scale;
    const nodeMap = new Map(powerNodes.value.map((node) => [node.id, node]));

    return powerLinkWidgets.value.flatMap((link, idx) => {
        const fromNode = nodeMap.get(link.x);
        const toNode = nodeMap.get(link.y);
        if (!fromNode || !toNode) return [];

        const lineWidth = Math.max(3, link.w || 3);
        const fromCenter = {
            x: (fromNode.x + fromNode.w / 2) * s,
            y: (fromNode.y + fromNode.h / 2) * s
        };
        const toCenter = {
            x: (toNode.x + toNode.w / 2) * s,
            y: (toNode.y + toNode.h / 2) * s
        };

        const dx = toCenter.x - fromCenter.x;
        const dy = toCenter.y - fromCenter.y;
        const len = Math.hypot(dx, dy) || 1;
        const ux = dx / len;
        const uy = dy / len;
        const fromRadius = Math.max(0, (Math.min(fromNode.w, fromNode.h) * 0.5 - lineWidth * 0.5) * s);
        const toRadius = Math.max(0, (Math.min(toNode.w, toNode.h) * 0.5 - lineWidth * 0.5) * s);

        let startX = fromCenter.x + ux * fromRadius;
        let startY = fromCenter.y + uy * fromRadius;
        let endX = toCenter.x - ux * toRadius;
        let endY = toCenter.y - uy * toRadius;

        if (len <= fromRadius + toRadius + 1) {
            startX = fromCenter.x;
            startY = fromCenter.y;
            endX = toCenter.x;
            endY = toCenter.y;
        }

        const dxTrim = endX - startX;
        const dyTrim = endY - startY;
        const lenTrim = Math.hypot(dxTrim, dyTrim) || 1;
        const nx = -dyTrim / lenTrim;
        const ny = dxTrim / lenTrim;
        const midX = (startX + endX) / 2;
        const midY = (startY + endY) / 2;
        const curveSign = idx % 2 === 0 ? 1 : -1;
        const curve = Math.min(42 * s, lenTrim * 0.3) * curveSign;
        const cpx = midX + nx * curve;
        const cpy = midY + ny * curve;
        const dotRadius = Math.min(8, Math.max(4, lineWidth * 1.6));
        const rawValue = parseFloat(link.text);
        const hasRaw = Number.isFinite(rawValue);
        const isStatic = (link.textSrc ?? 0) === 0;
        const factor = hasRaw ? rawValue : (isStatic ? 60 : 1);
        const previewValue = 50;
        const speed = Math.max(5, isStatic ? factor : Math.abs(previewValue) * factor);
        const duration = Math.max(2, Math.min(10, lenTrim / speed));

        return [{
            id: link.id,
            path: `M ${startX} ${startY} Q ${cpx} ${cpy} ${endX} ${endY}`,
            color: link.bgColor || '#6fa7d8',
            opacity: clamp((link.bgOpacity ?? 255) / 255, 0.1, 1),
            width: lineWidth,
            dotRadius,
            duration
        }];
    });
});

const powerFlowBgStyle = computed(() => {
    const alpha = clamp((props.widget.bgOpacity ?? 255) / 255, 0, 1);
    const base = hexToRgba(props.widget.bgColor, alpha);
    const dot = hexToRgba('#9aa7b4', 0.25);
    const dotSize = 16 * props.scale;

    return {
        backgroundColor: base,
        backgroundImage: `radial-gradient(${dot} 0.9px, transparent 1px), linear-gradient(140deg, rgba(255,255,255,0.9) 0%, ${base} 70%)`,
        backgroundSize: `${dotSize}px ${dotSize}px, 100% 100%`,
        backgroundPosition: '0 0, 0 0'
    };
});

const computedStyle = computed(() => {
    const w = props.widget;
    const s = props.scale;

    const style = {
        left: `${w.x * s}px`,
        top: `${w.y * s}px`,
        width: `${w.w * s}px`,
        height: `${w.h * s}px`,
        fontSize: `${(fontSizes[w.fontSize] || 14) * s}px`,
        color: w.textColor,
        position: 'absolute',
        zIndex: 1,
        cursor: 'move',
        userSelect: 'none',
        touchAction: 'none'
    };

    if (isIcon.value) {
        // Icon widget
        style.display = 'flex';
        style.alignItems = 'center';
        style.justifyContent = 'center';
        if (w.bgOpacity > 0) {
            const alpha = clamp(w.bgOpacity / 255, 0, 1).toFixed(2);
            style.background = hexToRgba(w.bgColor, alpha);
        }
        if (w.radius > 0) {
            style.borderRadius = `${w.radius * s}px`;
        }
    } else if (isLabel.value) {
        if (w.bgOpacity > 0) {
            const alpha = clamp(w.bgOpacity / 255, 0, 1).toFixed(2);
            style.background = hexToRgba(w.bgColor, alpha);
        }
        style.display = 'flex';
        style.alignItems = 'center';
        if (!hasIcon.value) {
            style.justifyContent = justifyForAlign(textAlign.value);
            style.textAlign = textAlignCss(textAlign.value);
        }
    } else if (isButton.value) {
        style.background = w.bgColor;
        style.borderRadius = `${w.radius * s}px`;
        style.display = 'flex';
        style.alignItems = 'center';
        style.justifyContent = contentJustify.value;
        style.fontWeight = '600';

        if (w.shadow && w.shadow.enabled) {
            const sx = (w.shadow.x || 0) * s;
            const sy = (w.shadow.y || 0) * s;
            const blur = (w.shadow.blur || 0) * s;
            const spread = (w.shadow.spread || 0) * s;
            style.boxShadow = `${sx}px ${sy}px ${blur}px ${spread}px ${w.shadow.color}`;
        }
    } else if (isLed.value) {
        style.borderRadius = '999px';

        const brightness = clamp((w.bgOpacity ?? 255) / 255, 0, 1);
        const glowColor = (w.shadow && w.shadow.color) ? w.shadow.color : w.bgColor;
        const highlight = clamp(brightness + 0.25, 0, 1);
        const core = clamp(brightness, 0, 1);
        const edge = clamp(brightness * 0.5, 0, 1);

        style.background = `radial-gradient(circle at 30% 30%, ${hexToRgba(w.bgColor, highlight)} 0%, ${hexToRgba(w.bgColor, core)} 45%, ${hexToRgba(w.bgColor, edge)} 70%, rgba(0,0,0,0.4) 100%)`;

        if (w.shadow && w.shadow.enabled) {
            const sx = (w.shadow.x || 0) * s;
            const sy = (w.shadow.y || 0) * s;
            const blur = (w.shadow.blur || 0) * s;
            const spread = (w.shadow.spread || 0) * s;
            const glowAlpha = clamp(0.4 + brightness * 0.6, 0, 1);
            style.boxShadow = `${sx}px ${sy}px ${blur}px ${spread}px ${hexToRgba(glowColor, glowAlpha)}`;
        } else {
            style.boxShadow = 'inset 0 0 0 1px rgba(255,255,255,0.12)';
        }
    } else if (isPowerFlow.value) {
        style.borderRadius = `${w.radius * s}px`;
        style.overflow = 'hidden';
        style.border = `1px solid ${hexToRgba('#94a3b8', 0.35)}`;
        if (w.shadow && w.shadow.enabled) {
            const sx = (w.shadow.x || 0) * s;
            const sy = (w.shadow.y || 0) * s;
            const blur = (w.shadow.blur || 0) * s;
            const spread = (w.shadow.spread || 0) * s;
            style.boxShadow = `${sx}px ${sy}px ${blur}px ${spread}px ${w.shadow.color}`;
        }
    } else if (isPowerNode.value) {
        const ringAlpha = clamp((w.bgOpacity ?? 255) / 255, 0, 1);
        const ring = Math.max(3, Math.round(Math.min(w.w, w.h) * 0.06 * s));

        style.display = 'flex';
        style.alignItems = 'center';
        style.justifyContent = 'center';
        style.borderRadius = '999px';
        style.background = hexToRgba('#ffffff', 0.96);
        style.border = `${ring}px solid ${hexToRgba(w.bgColor, ringAlpha)}`;
        style.textAlign = 'center';

        if (w.shadow && w.shadow.enabled) {
            const sx = (w.shadow.x || 0) * s;
            const sy = (w.shadow.y || 0) * s;
            const blur = (w.shadow.blur || 0) * s;
            const spread = (w.shadow.spread || 0) * s;
            const glowAlpha = clamp(0.35 + ringAlpha * 0.5, 0, 1);
            style.boxShadow = `${sx}px ${sy}px ${blur}px ${spread}px ${hexToRgba(w.shadow.color || w.bgColor, glowAlpha)}`;
        } else {
            style.boxShadow = '0 8px 18px rgba(15, 23, 42, 0.12)';
        }
        if (store.powerLinkMode.active && store.powerLinkMode.powerflowId === w.parentId) {
            style.cursor = 'crosshair';
        }
        if (store.powerLinkMode.active && store.powerLinkMode.fromNodeId === w.id && store.powerLinkMode.powerflowId === w.parentId) {
            style.outline = `2px dashed ${hexToRgba('#4f8ad9', 0.9)}`;
            style.outlineOffset = '2px';
        }
    } else if (isTabView.value) {
        style.background = w.bgColor;
        style.borderRadius = `${w.radius * s}px`;
        // No flex here, we handle internal layout manually
    } else if (isTabPage.value) {
        style.position = 'relative'; // Relative to content area
        style.width = '100%';
        style.height = '100%';
        style.left = '0';
        style.top = '0';
    }

    return style;
});

const tabViewStyle = computed(() => {
    return {
        flexDirection: tabPosition.value === 0 || tabPosition.value === 1 ? 'column' : 'row'
    };
});

const tabBtnsStyle = computed(() => {
    const s = props.scale;
    const h = tabHeight.value * s;
    const isVert = tabPosition.value === 0 || tabPosition.value === 1;
    
    return {
        [isVert ? 'height' : 'width']: `${h}px`,
        order: tabPosition.value === 1 || tabPosition.value === 3 ? 2 : 0, // Bottom/Right
        flexDirection: isVert ? 'row' : 'column'
    };
});

const tabBtnClass = (isActive) => {
    const isVerticalTabs = tabPosition.value === 2 || tabPosition.value === 3;
    const base = 'flex-1 flex items-center justify-center px-1 py-1 text-[12px] cursor-pointer select-none';
    const border = isVerticalTabs ? 'border-b border-white/10' : 'border-b border-r border-white/10';
    const active = isVerticalTabs
        ? 'bg-white/10 font-bold border-b-0 border-r-2 border-accent'
        : 'bg-white/10 font-bold border-b-2 border-accent';
    return `${base} ${border}${isActive ? ` ${active}` : ''}`;
};

function splitPowerNodeText(text) {
    if (typeof text !== 'string') return { label: '', value: '' };
    const parts = text.split('\n');
    const label = parts[0] ?? '';
    const value = parts.slice(1).join('\n');
    return { label, value };
}

function handleWidgetClick() {
    if (isPowerNode.value && store.powerLinkMode.active) {
        store.handlePowerNodeLink(props.widget.id, props.widget.parentId);
        return;
    }
    emit('select');
}
</script>
