import { useLayoutEffect, useRef } from "react";
import { Line } from "react-konva";
import Konva from "konva";
import type { ShapeProps } from "./types";
import { getKonvaGradientProps } from "../../utils/gradient";
import { getCustomShapePointBounds } from "../../utils/customShape";

/**
 * Renders a completed custom polygon shape using Konva.Line with closed=true.
 *
 * Points are stored as a flat array [x1,y1, x2,y2, …] relative to obj.x/obj.y,
 * matching Konva's native Line.points format. This design leaves room for future
 * Bézier curve support (by adding a separate controlPoints field) and path editing
 * (by rendering individual vertex handles when in edit mode).
 */
const CustomShape = ({ obj, isSelected, onSelect, onUpdate, draggable }: ShapeProps) => {
  const shapeRef = useRef<Konva.Line>(null);

  const points = obj.points ?? [];
  // Need at least 3 vertices (6 values) to render a polygon
  if (points.length < 6) return null;

  const actualStrokeWidth = obj.strokeWidth ?? 2;
  const hasStroke = actualStrokeWidth > 0;

  const displayStroke = isSelected
    ? (hasStroke ? obj.stroke : "#3b82f6")
    : (hasStroke ? obj.stroke : undefined);

  const displayStrokeWidth = isSelected
    ? (hasStroke ? actualStrokeWidth : 2)
    : actualStrokeWidth;

  const { minX, minY, width: bboxW, height: bboxH } =
    getCustomShapePointBounds(points);

  const gradientProps = getKonvaGradientProps(
    obj.fillType,
    obj.gradient,
    bboxW,
    bboxH,
    "rect",
    { x: minX, y: minY },
  );

  // Konva Line does not always react to gradient prop changes from react-konva.
  // Sync fill state imperatively so color / gradient edits apply immediately.
  useLayoutEffect(() => {
    const node = shapeRef.current;
    if (!node) return;

    if (obj.fillType === "gradient" && obj.gradient) {
      const props = getKonvaGradientProps(
        obj.fillType,
        obj.gradient,
        bboxW,
        bboxH,
        "rect",
        { x: minX, y: minY },
      );
      node.fillPriority("linear-gradient");
      node.fillLinearGradientStartPoint(props.fillLinearGradientStartPoint!);
      node.fillLinearGradientEndPoint(props.fillLinearGradientEndPoint!);
      node.fillLinearGradientColorStops(props.fillLinearGradientColorStops!);
    } else {
      node.fillPriority("color");
      node.fill(obj.fill ?? "#3b82f6");
    }

    node.getLayer()?.batchDraw();
  }, [
    obj.fillType,
    obj.fill,
    obj.gradient?.from,
    obj.gradient?.to,
    obj.gradient?.angle,
    bboxW,
    bboxH,
    minX,
    minY,
  ]);

  return (
    <Line
      ref={shapeRef}
      id={obj.id}
      name="canvas-object"
      x={obj.x}
      y={obj.y}
      points={points}
      closed={obj.closed ?? true}
      fill={obj.fill ?? "#3b82f6"}
      {...gradientProps}
      stroke={displayStroke}
      strokeWidth={displayStrokeWidth}
      perfectDrawEnabled={false}
      rotation={obj.rotation ?? 0}
      opacity={(obj.opacity ?? 100) / 100}
      draggable={draggable}
      onClick={(e) => {
        if (shapeRef.current) {
          onSelect(obj.id, shapeRef.current, e);
        }
      }}
      onDragMove={(e) => {
        e.target.getLayer()?.batchDraw();
      }}
      onDragEnd={(e) => {
        const node = e.target;
        onUpdate(obj.id, {
          x: node.x(),
          y: node.y(),
        });
      }}
    />
  );
};

export default CustomShape;
