<template>
  <div
    class="z-[1] select-none touch-none"
    :class="selected ? 'outline outline-2 outline-accent outline-offset-2' : ''"
    :style="computedStyle"
    @mousedown.stop="$emit('drag-start', { id: widget.id, event: $event })"
    @touchstart.stop="$emit('drag-start', { id: widget.id, event: $event })"
    @click.stop="$emit('select')"
  >
    <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)"
    />

    <!-- Resize Handle -->
    <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, defineAsyncComponent } from 'vue';
import { useEditorStore } from '../../../stores/editor';
import { WIDGET_TYPES } from '../../../constants';
import { getBaseStyle, getShadowStyle, getBorderStyle, clamp, hexToRgba } from '../shared/utils';

const WidgetElement = defineAsyncComponent(() => import('../../WidgetElement.vue'));

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

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 powerNodes = computed(() => {
  return children.value.filter((child) => child.type === WIDGET_TYPES.POWERNODE && child.visible !== false);
});

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

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

const powerFlowLinks = computed(() => {
  if (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 = getBaseStyle(w, s);
  style.borderRadius = `${w.radius * s}px`;
  style.overflow = 'hidden';
  if ((w.borderWidth || 0) > 0 && (w.borderOpacity ?? 0) > 0) {
    Object.assign(style, getBorderStyle(w, s));
  } else {
    style.border = `1px solid ${hexToRgba('#94a3b8', 0.35)}`;
  }

  Object.assign(style, getShadowStyle(w, s));

  return style;
});
</script>
