import type { EditorObject } from "../store/editorStore";

/**
 * exportUtils - Utilities برای export با real masking
 * 
 * CRITICAL: Real masking فقط در export اعمال می‌شود، نه در editor.
 * این تضمین می‌کند که masking هیچ‌وقت روی hit detection، selection،
 * grouping یا transforms تاثیر نگذارد.
 */

/**
 * رسم یک mask shape روی canvas context
 */
const drawMaskShape = (
  ctx: CanvasRenderingContext2D,
  maskShape: EditorObject
): void => {
  ctx.save();
  
  ctx.translate(maskShape.x || 0, maskShape.y || 0);
  ctx.rotate(((maskShape.rotation || 0) * Math.PI) / 180);
  
  ctx.fillStyle = "black";
  ctx.strokeStyle = "transparent";

  if (maskShape.type === "rectangle" && maskShape.shapeType === "circle") {
    const radius = (maskShape.width || 50) / 2;
    ctx.beginPath();
    ctx.arc(0, 0, radius, 0, Math.PI * 2);
    ctx.fill();
  } else if (maskShape.type === "rectangle" && maskShape.shapeType === "triangle") {
    const width = maskShape.width || 100;
    const height = maskShape.height || 100;
    const radius = Math.min(width / 2, height / 2);
    
    ctx.beginPath();
    ctx.translate(width / 2, height / 2);
    for (let i = 0; i < 3; i++) {
      const angle = (i * 2 * Math.PI) / 3 - Math.PI / 2;
      const x = radius * Math.cos(angle);
      const y = radius * Math.sin(angle);
      if (i === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    }
    ctx.closePath();
    ctx.fill();
  } else if (maskShape.type === "rectangle" && maskShape.shapeType === "abstract") {
    const width = maskShape.width || 100;
    const height = maskShape.height || 100;
    const baseRadius = Math.min(width / 2, height / 2);
    const abstractScale = 0.85;
    const outerRadius = baseRadius * abstractScale;
    const innerRadius = outerRadius * 0.5;
    const numPoints = 5;

    ctx.beginPath();
    ctx.translate(width / 2, height / 2);
    for (let i = 0; i < numPoints * 2; i++) {
      const radius = i % 2 === 0 ? outerRadius : innerRadius;
      const angle = (i * Math.PI) / numPoints - Math.PI / 2;
      const x = radius * Math.cos(angle);
      const y = radius * Math.sin(angle);
      if (i === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    }
    ctx.closePath();
    ctx.fill();
  } else {
    // Default: Rectangle
    const width = maskShape.width || 100;
    const height = maskShape.height || 100;
    const radius = Math.max(0, maskShape.borderRadius || 0);
    drawRoundedRectPath(ctx, 0, 0, width, height, radius);
    ctx.fill();
  }
  
  ctx.restore();
};

const drawRoundedRectPath = (
  ctx: CanvasRenderingContext2D,
  x: number,
  y: number,
  width: number,
  height: number,
  radius: number
): void => {
  const normalizedRadius = Math.max(0, Math.min(radius, width / 2, height / 2));
  ctx.beginPath();
  if (normalizedRadius === 0) {
    ctx.rect(x, y, width, height);
  } else {
    ctx.roundRect(x, y, width, height, normalizedRadius);
  }
  ctx.closePath();
};

/**
 * رسم یک object روی canvas context
 * این تابع یک نسخه ساده است - در پیاده‌سازی واقعی باید
 * از Konva stage.toCanvas() یا image rendering استفاده شود
 */
const drawObject = async (
  ctx: CanvasRenderingContext2D,
  object: EditorObject
): Promise<void> => {
  ctx.save();
  
  ctx.translate(object.x || 0, object.y || 0);
  ctx.rotate(((object.rotation || 0) * Math.PI) / 180);
  ctx.scale(object.scaleX || 1, object.scaleY || 1);
  
  // برای image objects
  if (object.type === "image" || object.type === "document" || object.type === "sticker") {
    if (object.imageUrl) {
      const img = new Image();
      img.crossOrigin = "anonymous";
      await new Promise((resolve, reject) => {
        img.onload = resolve;
        img.onerror = reject;
        img.src = object.imageUrl!;
      });
      ctx.drawImage(img, 0, 0, object.width || 100, object.height || 100);
    }
  }
  // برای shape objects
  else if (object.type === "rectangle") {
    ctx.fillStyle = object.fill || "#000000";
    ctx.strokeStyle = object.stroke || "transparent";
    ctx.lineWidth = object.strokeWidth || 0;
    
    if (object.shapeType === "circle") {
      const radius = (object.width || 50) / 2;
      ctx.beginPath();
      ctx.arc(0, 0, radius, 0, Math.PI * 2);
      ctx.fill();
      if (ctx.lineWidth > 0) ctx.stroke();
    } else {
      const width = object.width || 100;
      const height = object.height || 100;
      const radius = Math.max(0, object.borderRadius || 0);
      drawRoundedRectPath(ctx, 0, 0, width, height, radius);
      ctx.fill();
      if (ctx.lineWidth > 0) ctx.stroke();
    }
  }
  // برای text objects
  else if (object.type === "text") {
    ctx.fillStyle = object.fill || "#000000";
    ctx.font = `${object.fontWeight || "normal"} ${object.fontSize || 16}px ${object.fontFamily || "Arial"}`;
    ctx.fillText(object.text || "", 0, 0);
  }
  
  ctx.restore();
};

/**
 * Export یک object با masking به صورت data URL
 * 
 * @param object - Object برای export
 * @param maskShape - Mask shape برای اعمال (optional)
 * @returns Data URL (PNG)
 */
export const exportObjectWithMask = async (
  object: EditorObject,
  maskShape: EditorObject | null
): Promise<string> => {
  // محاسبه bounds
  const x = object.x || 0;
  const y = object.y || 0;
  const width = object.width || 100;
  const height = object.height || 100;

  // ایجاد offscreen canvas
  const canvas = document.createElement("canvas");
  canvas.width = width;
  canvas.height = height;
  const ctx = canvas.getContext("2d");
  
  if (!ctx) {
    throw new Error("Failed to get canvas context");
  }

  // اگر mask وجود ندارد، فقط object را draw کن
  if (!maskShape) {
    await drawObject(ctx, { ...object, x: 0, y: 0 });
    return canvas.toDataURL("image/png");
  }

  // Step 1: Draw object
  await drawObject(ctx, { ...object, x: 0, y: 0 });

  // Step 2: Apply mask — default is destination-in (show inside mask).
  // maskInvert === false → destination-out (show outside mask, hide inside).
  ctx.globalCompositeOperation = object.maskInvert === false ? "destination-out" : "destination-in";
  
  // Adjust mask position relative to object
  const adjustedMaskShape: EditorObject = {
    ...maskShape,
    x: (maskShape.x || 0) - x,
    y: (maskShape.y || 0) - y,
  };
  
  drawMaskShape(ctx, adjustedMaskShape);

  // Return PNG
  return canvas.toDataURL("image/png");
};

/**
 * Export تمام objects از یک page با masking
 * 
 * @param objects - لیست objects برای export
 * @returns Map از object IDs به data URLs
 */
export const exportPageWithMasks = async (
  objects: EditorObject[]
): Promise<Map<string, string>> => {
  const results = new Map<string, string>();

  for (const obj of objects) {
    // Skip masks themselves
    if (obj.isMask) {
      continue;
    }

    let maskShape: EditorObject | null = null;
    if (obj.maskId) {
      maskShape = objects.find((m) => m.id === obj.maskId) || null;
    }

    try {
      const dataUrl = await exportObjectWithMask(obj, maskShape);
      results.set(obj.id, dataUrl);
    } catch (error) {
      console.error(`Failed to export object ${obj.id}:`, error);
    }
  }

  return results;
};

/**
 * Export کل stage به عنوان یک image با masking اعمال شده
 * 
 * این تابع می‌تواند با Konva Stage API integrate شود
 * برای بهتر شدن quality و performance
 */
export const exportStageWithMasks = async (
  objects: EditorObject[],
  stageWidth: number,
  stageHeight: number,
  backgroundColor: string = "#ffffff"
): Promise<string> => {
  const canvas = document.createElement("canvas");
  canvas.width = stageWidth;
  canvas.height = stageHeight;
  const ctx = canvas.getContext("2d");
  
  if (!ctx) {
    throw new Error("Failed to get canvas context");
  }

  // Background
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, stageWidth, stageHeight);

  // Export هر object با mask
  const exports = await exportPageWithMasks(objects);
  
  // Draw exported images روی stage
  for (const [objId, dataUrl] of exports.entries()) {
    const obj = objects.find((o) => o.id === objId);
    if (!obj) continue;

    const img = new Image();
    await new Promise((resolve, reject) => {
      img.onload = resolve;
      img.onerror = reject;
      img.src = dataUrl;
    });

    ctx.drawImage(img, obj.x || 0, obj.y || 0);
  }

  return canvas.toDataURL("image/png");
};

