export type FillType = "solid" | "gradient";

export type LinearGradient = {
  from: string;
  to: string;
  angle: number;
};

type Point = { x: number; y: number };

type GradientPointMode = "rect" | "centered";

const toRadians = (angle: number) => (angle * Math.PI) / 180;

const normalizeAngle = (angle: number) => {
  if (!Number.isFinite(angle)) return 0;
  return ((angle % 360) + 360) % 360;
};

const getGradientPoints = (
  width: number,
  height: number,
  angle: number,
  mode: GradientPointMode,
): { start: Point; end: Point } => {
  const safeWidth = Math.max(1, width);
  const safeHeight = Math.max(1, height);
  // App/UI angle: 0° = top→bottom, 90° = left→right (clockwise).
  const rad = toRadians(normalizeAngle(angle));
  const half = Math.sqrt(safeWidth * safeWidth + safeHeight * safeHeight) / 2;
  const halfX = Math.sin(rad) * half;
  const halfY = Math.cos(rad) * half;

  if (mode === "centered") {
    return {
      start: { x: -halfX, y: -halfY },
      end: { x: halfX, y: halfY },
    };
  }

  const cx = safeWidth / 2;
  const cy = safeHeight / 2;
  return {
    start: { x: cx - halfX, y: cy - halfY },
    end: { x: cx + halfX, y: cy + halfY },
  };
};

export const getKonvaGradientProps = (
  fillType: FillType | undefined,
  gradient: LinearGradient | undefined,
  width: number,
  height: number,
  mode: GradientPointMode,
  offset: Point = { x: 0, y: 0 },
) => {
  if (fillType !== "gradient" || !gradient) return {};
  const points = getGradientPoints(width, height, gradient.angle, mode);
  return {
    fillPriority: "linear-gradient" as const,
    fillLinearGradientStartPoint: {
      x: points.start.x + offset.x,
      y: points.start.y + offset.y,
    },
    fillLinearGradientEndPoint: {
      x: points.end.x + offset.x,
      y: points.end.y + offset.y,
    },
    fillLinearGradientColorStops: [0, gradient.from, 1, gradient.to] as [
      number,
      string,
      number,
      string,
    ],
  };
};

/** SVG linearGradient endpoints matching the Konva gradient math. */
export const getSvgGradientEndpoints = (
  gradient: LinearGradient,
  width: number,
  height: number,
  mode: GradientPointMode = "rect",
  offset: Point = { x: 0, y: 0 },
) => {
  const points = getGradientPoints(width, height, gradient.angle, mode);
  return {
    x1: points.start.x + offset.x,
    y1: points.start.y + offset.y,
    x2: points.end.x + offset.x,
    y2: points.end.y + offset.y,
  };
};

/** Convert app/UI angle to CSS linear-gradient degrees (0deg = upward in CSS). */
export const toCssGradientAngle = (angle: number) =>
  normalizeAngle(180 - normalizeAngle(angle));

export const toCssLinearGradient = (gradient: LinearGradient | undefined) => {
  if (!gradient) return undefined;
  return `linear-gradient(${toCssGradientAngle(gradient.angle)}deg, ${gradient.from} 0%, ${gradient.to} 100%)`;
};
