import type { CSSProperties } from 'react';
import type { EditorObject } from '@/pages/editor/store/editorStore';

type Bounds = {
  left: number;
  top: number;
  right: number;
  bottom: number;
};

export type MaskedLayout = {
  left: number;
  top: number;
  width: number;
  height: number;
  maskRelX: number;
  maskRelY: number;
};

const encodeSvg = (svg: string) =>
  `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;

const getObjectBounds = (obj: EditorObject): Bounds => {
  if (obj.type === 'rectangle' && obj.shapeType === 'circle') {
    const radius = (obj.width || 100) / 2;
    const cx = obj.x || 0;
    const cy = obj.y || 0;
    return {
      left: cx - radius,
      top: cy - radius,
      right: cx + radius,
      bottom: cy + radius,
    };
  }

  if (obj.type === 'rectangle' && (obj.shapeType === 'triangle' || obj.shapeType === 'abstract')) {
    const width = obj.width || 100;
    const height = obj.height || 100;
    const radius = Math.min(width, height) / 2;
    const cx = (obj.x || 0) + width / 2;
    const cy = (obj.y || 0) + height / 2;
    return {
      left: cx - radius,
      top: cy - radius,
      right: cx + radius,
      bottom: cy + radius,
    };
  }

  return {
    left: obj.x || 0,
    top: obj.y || 0,
    right: (obj.x || 0) + (obj.width || 100),
    bottom: (obj.y || 0) + (obj.height || 100),
  };
};

const getMaskBounds = (mask: EditorObject): Bounds => {
  if (mask.type === 'rectangle' && mask.shapeType === 'circle') {
    const radius = (mask.width || 100) / 2;
    const cx = mask.x || 0;
    const cy = mask.y || 0;
    return {
      left: cx - radius,
      top: cy - radius,
      right: cx + radius,
      bottom: cy + radius,
    };
  }

  if (mask.type === 'rectangle' && mask.shapeType === 'triangle') {
    const width = mask.width || 100;
    const height = mask.height || 100;
    const radius = Math.min(width, height) / 2;
    const cx = (mask.x || 0) + width / 2;
    const cy = (mask.y || 0) + height / 2;
    return {
      left: cx - radius,
      top: cy - radius,
      right: cx + radius,
      bottom: cy + radius,
    };
  }

  if (mask.type === 'rectangle' && mask.shapeType === 'abstract') {
    const width = mask.width || 100;
    const height = mask.height || 100;
    const baseRadius = Math.min(width, height) / 2;
    const radius = baseRadius * 0.85;
    const cx = (mask.x || 0) + width / 2;
    const cy = (mask.y || 0) + height / 2;
    return {
      left: cx - radius,
      top: cy - radius,
      right: cx + radius,
      bottom: cy + radius,
    };
  }

  return {
    left: mask.x || 0,
    top: mask.y || 0,
    right: (mask.x || 0) + (mask.width || 100),
    bottom: (mask.y || 0) + (mask.height || 100),
  };
};

/**
 * Computes the wrapper bounding box for a masked object.
 *
 * Default (maskInvert !== false) → destination-in → show inside mask:
 *   Uses intersection bounds — only the overlap area needs to be rendered,
 *   which is smaller and faster than the union.
 *
 * maskInvert === false → destination-out → show outside mask (hide inside):
 *   Uses object bounds — the entire object is visible except where the mask sits.
 */
export const getMaskedLayout = (
  obj: EditorObject,
  mask: EditorObject,
  scale: number,
): MaskedLayout => {
  const objBounds = getObjectBounds(obj);
  const maskBounds = getMaskBounds(mask);

  const isDestinationIn = obj.maskInvert !== false;

  let left: number;
  let top: number;
  let right: number;
  let bottom: number;

  if (isDestinationIn) {
    // Show inside mask: only the intersection area will be visible.
    // Use intersection bounds to minimise the wrapper size.
    left = Math.max(objBounds.left, maskBounds.left);
    top = Math.max(objBounds.top, maskBounds.top);
    right = Math.min(objBounds.right, maskBounds.right);
    bottom = Math.min(objBounds.bottom, maskBounds.bottom);

    if (right <= left || bottom <= top) {
      // No overlap — nothing to render.
      return { left: left * scale, top: top * scale, width: 0, height: 0, maskRelX: 0, maskRelY: 0 };
    }
  } else {
    // Show outside mask: the full object area is the canvas.
    // The mask shape (drawn black) will punch a hole inside it.
    left = objBounds.left;
    top = objBounds.top;
    right = objBounds.right;
    bottom = objBounds.bottom;
  }

  const maskRelX = (mask.x || 0) - left;
  const maskRelY = (mask.y || 0) - top;

  return {
    left: left * scale,
    top: top * scale,
    width: Math.max(1, (right - left) * scale),
    height: Math.max(1, (bottom - top) * scale),
    maskRelX: maskRelX * scale,
    maskRelY: maskRelY * scale,
  };
};

const renderMaskShapeSvg = (
  mask: EditorObject,
  relX: number,
  relY: number,
  scale: number,
  fill: string,
): string => {
  const width = (mask.width || 100) * scale;
  const height = (mask.height || 100) * scale;
  const rotation = mask.rotation || 0;

  if (mask.type === 'rectangle' && mask.shapeType === 'circle') {
    const radius = width / 2;
    return `<circle cx="${relX}" cy="${relY}" r="${radius}" fill="${fill}" transform="rotate(${rotation} ${relX} ${relY})" />`;
  }

  if (mask.type === 'rectangle' && mask.shapeType === 'triangle') {
    const radius = Math.min(width, height) / 2;
    const cx = relX + width / 2;
    const cy = relY + height / 2;
    const size = radius * 2;
    const triangleHeight = size * 0.8660254;
    const topY = (size - triangleHeight) / 2;
    const bottomY = size - topY;
    const halfWidth = triangleHeight * 0.5773503;
    const topX = size / 2;
    const bottomLeftX = size / 2 - halfWidth;
    const bottomRightX = size / 2 + halfWidth;
    const offsetX = cx - radius;
    const offsetY = cy - radius;
    return `<polygon points="${topX + offsetX},${topY + offsetY} ${bottomLeftX + offsetX},${bottomY + offsetY} ${bottomRightX + offsetX},${bottomY + offsetY}" fill="${fill}" transform="rotate(${rotation} ${cx} ${cy})" />`;
  }

  if (mask.type === 'rectangle' && mask.shapeType === 'abstract') {
    const baseRadius = Math.min(width, height) / 2;
    const radius = baseRadius * 0.85;
    const cx = relX + width / 2;
    const cy = relY + height / 2;
    const left = cx - radius;
    const top = cy - radius;
    const size = radius * 2;
    return `<polygon points="${left + size * 0.5},${top} ${left + size * 0.61},${top + size * 0.35} ${left + size * 0.98},${top + size * 0.35} ${left + size * 0.68},${top + size * 0.57} ${left + size * 0.79},${top + size * 0.91} ${left + size * 0.5},${top + size * 0.7} ${left + size * 0.21},${top + size * 0.91} ${left + size * 0.32},${top + size * 0.57} ${left + size * 0.02},${top + size * 0.35} ${left + size * 0.39},${top + size * 0.35}" fill="${fill}" transform="rotate(${rotation} ${cx} ${cy})" />`;
  }

  const cornerRadius = Math.max(0, (mask.borderRadius ?? 0) * scale);
  const rectX = relX;
  const rectY = relY;
  const pivotX = rectX;
  const pivotY = rectY;
  return `<rect x="${rectX}" y="${rectY}" width="${width}" height="${height}" rx="${cornerRadius}" ry="${cornerRadius}" fill="${fill}" transform="rotate(${rotation} ${pivotX} ${pivotY})" />`;
};

/**
 * Builds CSS mask properties matching editor Konva destination-in / destination-out.
 *
 * Default (maskInvert !== false) → destination-in → show inside mask:
 *   bg = black (hide everything), shape = white (reveal mask area)
 *
 * maskInvert === false → destination-out → show outside mask (hide inside):
 *   bg = white (show everything), shape = black (hide mask area)
 */
export const getMaskImageStyle = (
  obj: EditorObject,
  mask: EditorObject,
  scale: number,
  layout: MaskedLayout,
): CSSProperties => {
  const canvasW = layout.width;
  const canvasH = layout.height;

  // Default behaviour: show only inside the mask (destination-in)
  const showInsideMask = obj.maskInvert !== false;
  const bgFill = showInsideMask ? 'black' : 'white';
  const shapeFill = showInsideMask ? 'white' : 'black';

  const maskShapeX = layout.maskRelX;
  const maskShapeY = layout.maskRelY;

  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${canvasW} ${canvasH}"><rect width="100%" height="100%" fill="${bgFill}"/>${renderMaskShapeSvg(mask, maskShapeX, maskShapeY, scale, shapeFill)}</svg>`;
  const maskUrl = encodeSvg(svg);

  return {
    WebkitMaskImage: maskUrl,
    maskImage: maskUrl,
    WebkitMaskSize: `${canvasW}px ${canvasH}px`,
    maskSize: `${canvasW}px ${canvasH}px`,
    WebkitMaskPosition: '0 0',
    maskPosition: '0 0',
    WebkitMaskRepeat: 'no-repeat',
    maskRepeat: 'no-repeat',
    maskMode: 'luminance',
    // Safari needs luminance mode for white/black SVG fills
    ['WebkitMaskMode' as string]: 'luminance',
  };
};
