/**
 * 基于小程序Canvas API的核密度估计热力图
 * 实现类似test.html中的效果，但适配uni-app小程序环境
 */

/**
 * Epanechnikov核函数
 * @param {Number} bandwidth 带宽参数
 * @returns {Function} 核函数
 */
function kernelEpanechnikov(bandwidth) {
  return function (v) {
    const r = Math.sqrt(v[0] * v[0] + v[1] * v[1]);
    return r <= bandwidth
      ? (3 / (Math.PI * bandwidth * bandwidth)) *
          (1 - (r * r) / (bandwidth * bandwidth))
      : 0;
  };
}

/**
 * 核密度估计器
 * @param {Function} kernel 核函数
 * @param {Array} range 范围[xmin, xmax]
 * @param {Number} samples 采样点数
 * @returns {Function} 密度估计函数
 */
function kernelDensityEstimator(kernel, range, samples) {
  return function (data) {
    const gridSize = (range[1] - range[0]) / samples;
    const densityData = [];

    for (let x = range[0]; x <= range[1]; x += gridSize) {
      for (let y = range[0]; y <= range[1]; y += gridSize) {
        let sum = 0;
        for (const point of data) {
          sum += kernel([x - point[0], y - point[1]]);
        }
        densityData.push([x, y, sum / data.length]);
      }
    }

    // 归一化
    const maxDensity = Math.max(...densityData.map((d) => d[2]));
    densityData.forEach((d) => {
      if (maxDensity > 0) d[2] /= maxDensity;
    });

    return densityData;
  };
}

/**
 * 生成随机射箭数据点
 * @param {Number} centerCount 中心点数量
 * @param {Number} pointsPerCenter 每个中心点的箭数
 * @returns {Array} 箭矢坐标数组
 */
export function generateArcheryPoints(centerCount = 2, pointsPerCenter = 100) {
  const points = [];
  const range = 8; // 坐标范围 -4 到 4
  const spread = 3; // 分散度

  for (let i = 0; i < centerCount; i++) {
    const centerX = Math.random() * range - range / 2;
    const centerY = Math.random() * range - range / 2;

    for (let j = 0; j < pointsPerCenter; j++) {
      points.push([
        centerX + (Math.random() - 0.5) * spread,
        centerY + (Math.random() - 0.5) * spread,
      ]);
    }
  }

  return points;
}

/**
 * 颜色映射函数 - 将密度值映射到颜色
 * @param {Number} density 密度值 0-1
 * @returns {String} RGBA颜色字符串
 */
function getHeatColor(density) {
  // 绿色系热力图：从浅绿到深绿
  if (density < 0.1) return "rgba(0, 255, 0, 0)";

  const alpha = Math.min(density * 1.2, 1); // 增强透明度
  const intensity = density;

  if (intensity < 0.5) {
    // 低密度：浅绿色
    const green = Math.round(200 + 55 * intensity);
    const blue = Math.round(50 + 100 * intensity);
    return `rgba(${Math.round(50 * intensity)}, ${green}, ${blue}, ${
      alpha * 0.7
    })`;
  } else {
    // 高密度：深绿色
    const red = Math.round(50 * (intensity - 0.5) * 2);
    const green = Math.round(180 + 75 * (1 - intensity));
    const blue = Math.round(30 * (1 - intensity));
    return `rgba(${red}, ${green}, ${blue}, ${alpha * 0.7})`;
  }
}

/**
 * 基于小程序Canvas API绘制核密度估计热力图
 * @param {String} canvasId 画布ID
 * @param {Number} width 画布宽度
 * @param {Number} height 画布高度
 * @param {Array} points 箭矢坐标数组 [[x, y], ...]
 * @param {Object} options 可选参数
 * @returns {Promise} 绘制完成的Promise
 */
export function drawKDEHeatmap(canvasId, width, height, points, options = {}) {
  const {
    bandwidth = 0.8,
    gridSize = 100,
    range = [-4, 4],
    showPoints = true,
    pointColor = "rgba(255, 255, 255, 0.9)",
  } = options;

  // 微信小程序使用 Canvas 2D
  return new Promise((resolve, reject) => {
    try {
      wx.createSelectorQuery()
        .select(`#${canvasId}`)
        .fields({ node: true, size: true })
        .exec((res) => {
          try {
            const { node: canvas, width: w, height: h } = res[0] || {};
            if (!canvas) return resolve();

            // 设置画布尺寸
            const cw = width || w || 300;
            const ch = height || h || 300;
            canvas.width = cw;
            canvas.height = ch;

            const ctx = canvas.getContext("2d");
            ctx.clearRect(0, 0, cw, ch);

            if (!points || points.length === 0) return resolve();

            // 计算核密度估计
            const kernel = kernelEpanechnikov(bandwidth);
            const kde = kernelDensityEstimator(kernel, range, gridSize);
            const densityData = kde(points);

            // 计算网格大小
            const cellWidth = cw / gridSize;
            const cellHeight = ch / gridSize;
            const xRange = range[1] - range[0];
            const yRange = range[1] - range[0];

            // 绘制热力图网格
            densityData.forEach(([x, y, density]) => {
              const normalizedX = (x - range[0]) / xRange;
              const normalizedY = (y - range[0]) / yRange;
              const canvasX = normalizedX * cw;
              const canvasY = normalizedY * ch;

              const color = getHeatColor(density);
              ctx.fillStyle = color;
              ctx.beginPath();
              ctx.arc(
                canvasX,
                canvasY,
                Math.min(cellWidth, cellHeight) * 0.6,
                0,
                2 * Math.PI
              );
              ctx.fill();
            });

            // 绘制原始数据点
            if (showPoints) {
              ctx.fillStyle = pointColor;
              points.forEach(([x, y]) => {
                const normalizedX = (x - range[0]) / xRange;
                const normalizedY = (y - range[0]) / yRange;
                const canvasX = normalizedX * cw;
                const canvasY = normalizedY * ch;
                ctx.beginPath();
                ctx.arc(canvasX, canvasY, 2.5, 0, 2 * Math.PI);
                ctx.fill();
              });
            }

            resolve();
          } catch (err) {
            reject(err);
          }
        });
    } catch (error) {
      reject(error);
    }
  });
}

/**
 * 生成热力图图片（类似原有的generateHeatmapImage函数）
 * 但使用核密度估计算法
 */
export function generateKDEHeatmapImage(
  canvasId,
  width,
  height,
  points,
  options = {}
) {
  // Canvas 2D 导出（传入 canvas 对象）
  return new Promise((resolve, reject) => {
    drawKDEHeatmap(canvasId, width, height, points, options)
      .then(() => {
        try {
          wx.createSelectorQuery()
            .select(`#${canvasId}`)
            .fields({ node: true, size: true })
            .exec((res) => {
              const { node: canvas, width: w, height: h } = res[0] || {};
              if (!canvas) return reject(new Error("canvas 为空"));
              const cw = width || w || 300;
              const ch = height || h || 300;
              uni.canvasToTempFilePath({
                canvas,
                width: cw,
                height: ch,
                destWidth: cw * 3,
                destHeight: ch * 3,
                success: (r) => resolve(r.tempFilePath),
                fail: reject,
              });
            });
        } catch (e) {
          reject(e);
        }
      })
      .catch(reject);
  });
}

export const generateHeatMapData = (width, height, amount = 100) => {
  const data = [];
  const centerX = 0.5; // 中心点X坐标
  const centerY = 0.5; // 中心点Y坐标

  for (let i = 0; i < amount; i++) {
    let x, y;

    // 30%的数据集中在中心区域（高斯分布）
    if (Math.random() < 0.3) {
      // 使用正态分布生成中心区域的数据
      const angle = Math.random() * 2 * Math.PI;
      const radius = Math.sqrt(-2 * Math.log(Math.random())) * 0.15; // 标准差0.15
      x = centerX + radius * Math.cos(angle);
      y = centerY + radius * Math.sin(angle);
    } else {
      x = Math.random() * 0.8 + 0.1; // 0.1-0.9范围
      y = Math.random() * 0.8 + 0.1;
    }

    // 确保坐标在0-1范围内
    x = Math.max(0.05, Math.min(0.95, x));
    y = Math.max(0.05, Math.min(0.95, y));

    data.push({
      x: parseFloat(x.toFixed(3)),
      y: parseFloat(y.toFixed(3)),
      ring: Math.floor(Math.random() * 5) + 6, // 6-10环
    });
  }

  return data;
};
