const loadImage = (file) =>
  new Promise((resolve, reject) => {
    const image = new Image();
    image.onload = () => {
      URL.revokeObjectURL(image.src);
      resolve(image);
    };
    image.onerror = (error) => {
      URL.revokeObjectURL(image.src);
      reject(error);
    };
    image.src = URL.createObjectURL(file);
  });

const clamp = (value, min, max) => Math.min(Math.max(value, min), max);

const normalizeCropConfig = (config) => {
  if (!config?.imageWidth || !config?.imageHeight) {
    throw new Error('Geçerli bir crop referansı bulunamadı.');
  }
  const safeWidth = Math.max(
    1,
    config.width - (config.left ?? 0) - (config.right ?? 0),
  );
  const safeHeight = Math.max(
    1,
    config.height - (config.top ?? 0) - (config.bottom ?? 0),
  );
  const xStart = Math.max(0, config.cropAreaX + (config.left ?? 0));
  const yStart = Math.max(0, config.cropAreaY + (config.top ?? 0));
  return {
    xRatio: xStart / config.imageWidth,
    yRatio: yStart / config.imageHeight,
    widthRatio: safeWidth / config.imageWidth,
    heightRatio: safeHeight / config.imageHeight,
  };
};

const cropImage = async (file, normalizedConfig) => {
  const image = await loadImage(file);
  const { width: imgWidth, height: imgHeight } = image;
  const cropWidth = clamp(
    Math.round(normalizedConfig.widthRatio * imgWidth),
    1,
    imgWidth,
  );
  const cropHeight = clamp(
    Math.round(normalizedConfig.heightRatio * imgHeight),
    1,
    imgHeight,
  );
  const startX = clamp(
    Math.round(normalizedConfig.xRatio * imgWidth),
    0,
    imgWidth - cropWidth,
  );
  const startY = clamp(
    Math.round(normalizedConfig.yRatio * imgHeight),
    0,
    imgHeight - cropHeight,
  );

  const canvas = document.createElement('canvas');
  canvas.width = cropWidth;
  canvas.height = cropHeight;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(image, startX, startY, cropWidth, cropHeight, 0, 0, cropWidth, cropHeight);

  const blob = await new Promise((resolve, reject) => {
    canvas.toBlob((result) => {
      if (result) {
        resolve(result);
      } else {
        reject(new Error('Canvas blob oluşturulamadı.'));
      }
    }, 'image/png');
  });

  const url = URL.createObjectURL(blob);
  return { blob, url };
};

const buildCropResult = (imageMeta, blob, url) => ({
  id: imageMeta.id,
  filename: imageMeta.file?.name || imageMeta.filename,
  blob,
  url,
  order: imageMeta.order,
});

export const cropSingleImage = async (image, config) => {
  if (!config || !config.imageWidth) {
    throw new Error('Kapak için geçerli bir crop ayarı bulunamadı.');
  }
  const normalized = normalizeCropConfig(config);
  const { blob, url } = await cropImage(image.file, normalized);
  return buildCropResult(image, blob, url);
};

export const applyCropToImages = async (images, config) => {
  if (!images?.length) {
    throw new Error('Önce görsel yüklemelisin.');
  }
  if (!config || !config.imageWidth) {
    throw new Error('Crop ayarı bulunamadı.');
  }
  const normalized = normalizeCropConfig(config);
  const results = [];
  for (const image of images) {
    const { blob, url } = await cropImage(image.file, normalized);
    results.push(buildCropResult(image, blob, url));
  }
  return results;
};
