const config = require('../../../config/config.js');
const apiClient = require('../../../utils/api-client.js');
const cosManager = require('../../../utils/cos-manager.js');
Page({
  data: {
    currentTool: '',
    isCanvasInit: false,
    canvasContext: null,
    canvas: null,
    systemInfo: {},

    isRotated: false,

    // 相机状态
    cameraPosition: 'back',  // 默认后置摄像头
    flashState: 'off',       // 默认关闭闪光灯
    hasTakenPhoto: false,    // 是否已拍摄照片

    // 图片状态
    originalPhotoPath: '',   // 原始照片路径
    currentPhotoPath: '',    // 当前编辑的照片路径
    imageInfo: null,         // 图片信息
    imageScale: 1,           // 图片缩放比例
    imagePosition: {         // 图片在屏幕上的位置
      left: 0,
      top: 0,
      width: 0,
      height: 0
    },

    // 裁剪相关
    isCropping: false,
    cropBox: {
      left: 100,
      top: 200,
      width: 400,
      height: 400,
      right: 500,
      bottom: 600
    },
    cropStartPos: null,
    draggingHandle: null,
    isMovingCropBox: false,
    containerRect: null, // 图片容器的位置信息

    // 旋转相关
    rotateAngle: 0,

    // 马赛克相关
    mosaicData: [],          // 存储马赛克数据
    hasMosaic: false,        // 是否有马赛克
    mosaicSize: 25,          // 初始马赛克大小
    sizePercent: 50,         // 滑块初始位置百分比
    dragStartX: 0,           // 触摸起始 X 坐标
    canvasWidth: 0,          // 画布宽度
    canvasHeight: 0,         // 画布高度

    // 编辑状态
    hasEdits: false,         // 是否有编辑操作

    imageRect: {
      left: 0,
      top: 0,
      width: 0,
      height: 0
    }
  },

  // 获取容器位置（在开启裁剪时调用）
  updateContainerRect() {
    return new Promise((resolve) => {
      const query = wx.createSelectorQuery().in(this);
      query.select('.image-container').boundingClientRect((rect) => {
        if (rect) {
          this.setData({ containerRect: rect });
          resolve(rect);
        } else {
          resolve(null);
        }
      }).exec();
    });
  },

  // 拖动整个裁剪框（优化版本，使用缓存的容器位置）
  startCropMove(e) {
    if (!this.data.isCropping) return;
    
    const touch = e.touches[0];
    const { cropBox, imagePosition, containerRect } = this.data;
    
    if (!cropBox || !imagePosition) return;
    
    // 保存触摸坐标，避免异步回调中失效
    const touchX = touch.clientX;
    const touchY = touch.clientY;
    
    // 优先使用缓存的容器位置，避免异步延迟
    if (containerRect) {
      const relativeX = touchX - containerRect.left;
      const relativeY = touchY - containerRect.top;
      
      // 检查是否点击在裁剪框内
      const isInsideCropBox = relativeX >= cropBox.left && relativeX <= cropBox.right &&
                              relativeY >= cropBox.top && relativeY <= cropBox.bottom;
      
      if (isInsideCropBox) {
        // 记录起始位置
        this.setData({
          cropStartPos: {
            x: touchX,
            y: touchY,
            relativeX: relativeX,
            relativeY: relativeY,
            cropX: cropBox.left,
            cropY: cropBox.top
          },
          draggingHandle: null,
          isMovingCropBox: true
        });
      }
      return;
    }
    
    // 如果没有缓存的容器位置，异步获取（兼容旧代码）
    const query = wx.createSelectorQuery().in(this);
    query.select('.image-container').boundingClientRect((rect) => {
      if (!rect) return;
      
      const relativeX = touchX - rect.left;
      const relativeY = touchY - rect.top;
      
      // 检查是否点击在裁剪框内
      const isInsideCropBox = relativeX >= cropBox.left && relativeX <= cropBox.right &&
                              relativeY >= cropBox.top && relativeY <= cropBox.bottom;
      
      if (isInsideCropBox) {
        // 记录起始位置，并缓存容器位置
        this.setData({
          cropStartPos: {
            x: touchX,
            y: touchY,
            relativeX: relativeX,
            relativeY: relativeY,
            cropX: cropBox.left,
            cropY: cropBox.top
          },
          draggingHandle: null,
          isMovingCropBox: true,
          containerRect: rect
        });
      }
    }).exec();
  },

  // 滑动 slider 时触发
  onSliderChange(e) {
    const percent = e.detail.value;
    const newSize = 5 + (percent / 100) * 25;
    this.setData({
      sizePercent: percent,
      mosaicSize: newSize
    });
  },

  onLoad() {
    try {
      const systemInfo = wx.getSystemInfoSync();
      this.setData({ systemInfo });
      this.systemInfo = systemInfo;
    } catch (err) {
      console.error('获取系统信息失败:', err);
    }
    // 初始化双击检测变量（不使用 setData，避免不必要的渲染）
    this.lastTapTime = 0;
    this.tapTimer = null;
    // 移除手动权限检查，让 <camera> 组件自动处理权限请求
    // 这样可以避免权限弹窗弹出两次（组件初始化时会自动请求权限）
  },

  toggleFlash() {
    const newState = this.data.flashState === 'off' ? 'torch' : 'off';
    this.setData({ flashState: newState });
  },

  switchCamera() {
    const newPosition = this.data.cameraPosition === 'back' ? 'front' : 'back';
    this.setData({ cameraPosition: newPosition });
  },

  // 双击切换摄像头（优化版本，使用局部变量，响应更快）
  onCameraDoubleTap(e) {
    const currentTime = Date.now();
    const timeDiff = currentTime - this.lastTapTime;

    // 清除之前的定时器
    if (this.tapTimer) {
      clearTimeout(this.tapTimer);
      this.tapTimer = null;
    }

    // 如果两次点击间隔小于 250ms，认为是双击
    if (timeDiff < 250 && this.lastTapTime !== 0) {
      // 立即执行切换摄像头
      this.switchCamera();
      // 重置时间，防止连续触发
      this.lastTapTime = 0;
    } else {
      // 记录本次点击时间（使用实例变量，不触发 setData）
      this.lastTapTime = currentTime;
      // 250ms 后重置，防止误触发
      this.tapTimer = setTimeout(() => {
        this.lastTapTime = 0;
        this.tapTimer = null;
      }, 250);
    }
  },

  chooseFromAlbum() {
    wx.chooseMedia({
      count: 1,
      mediaType: ['image'],
      sourceType: ['album'],
      success: (res) => {
        const tempImagePath = res.tempFiles[0].tempFilePath;
        wx.getImageInfo({
          src: tempImagePath,
          success: (info) => {
            this.setData({
              originalPhotoPath: tempImagePath,
              currentPhotoPath: tempImagePath,
              imageInfo: info,
              hasTakenPhoto: true,
              hasEdits: false,
              rotateAngle: 0,
              mosaicData: [],
              hasMosaic: false,
              // 选择图片后初始化裁剪框
              cropBox: this.calculateInitialCropBox(info)
            }, () => {
              this.initMosaicCanvas();
            });
          }
        });
      },
      fail: (err) => {
        console.error('选择图片失败:', err);
        wx.showToast({
          title: '选择图片失败',
          icon: 'none'
        });
      }
    });
  },

  takePhoto() {
    const ctx = wx.createCameraContext();

    ctx.takePhoto({
      quality: 'high',
      success: (res) => {
        wx.getImageInfo({
          src: res.tempImagePath,
          success: (info) => {
            this.setData({
              originalPhotoPath: res.tempImagePath,
              currentPhotoPath: res.tempImagePath,
              imageInfo: info,
              hasTakenPhoto: true,
              hasEdits: false,
              rotateAngle: 0,
              mosaicData: [],
              hasMosaic: false,
              // 拍照后初始化裁剪框
              cropBox: this.calculateInitialCropBox()
            }, () => {
              this.initMosaicCanvas();
            });
          }
        });
      },
      fail: (err) => {
        console.error('拍照失败:', err);
        wx.showToast({
          title: '拍照失败',
          icon: 'none'
        });
      }
    });
  },

  // 计算初始裁剪框（确保在可视区域内）
  calculateInitialCropBox(imageInfo) {
    const targetImageInfo = imageInfo || this.data.imageInfo;
    const imagePosition = this.data.imagePosition || { width: 0, height: 0 };

    if (!targetImageInfo || !imagePosition.width || !imagePosition.height) {
      return { left: 0, top: 0, width: 100, height: 100, right: 100, bottom: 100 };
    }

    // 使用图片显示尺寸（相对于容器）
    const displayWidth = imagePosition.width;
    const displayHeight = imagePosition.height;
    const minCropSize = 80; // 最小裁剪尺寸

    // 初始裁剪框大小为图片的70%，但确保不小于最小尺寸
    const cropSize = Math.max(
      minCropSize,
      Math.min(displayWidth, displayHeight) * 0.7
    );
    
    // 居中显示，确保在图片范围内
    let cropX = (displayWidth - cropSize) / 2;
    let cropY = (displayHeight - cropSize) / 2;
    
    // 确保裁剪框完全在图片可视区域内
    cropX = Math.max(0, Math.min(cropX, displayWidth - cropSize));
    cropY = Math.max(0, Math.min(cropY, displayHeight - cropSize));

    return {
      left: cropX,
      top: cropY,
      width: cropSize,
      height: cropSize,
      right: cropX + cropSize,
      bottom: cropY + cropSize
    };
  },

  onImageLoaded(e) {
    const { width, height } = e.detail;
    const { systemInfo, imageScale } = this.data;

    const scale = imageScale || Math.min(
      systemInfo.windowWidth / width,
      systemInfo.windowHeight * 0.8 / height
    );

    const displayWidth = width * scale;
    const displayHeight = height * scale;
    const imageLeft = (systemInfo.windowWidth - displayWidth) / 2;
    const imageTop = (systemInfo.windowHeight - displayHeight) / 2;

    // 获取图片容器的实际尺寸（用于裁剪框计算）
    const query = wx.createSelectorQuery().in(this);
    query.select('.image-container').boundingClientRect((rect) => {
      // 容器尺寸（用于裁剪框计算，裁剪框相对于容器定位）
      const containerWidth = rect ? rect.width : displayWidth;
      const containerHeight = rect ? rect.height : displayHeight;
      
      // 更新图片位置信息
      // imageRect: 绝对位置（用于显示）
      // imagePosition: 相对于容器的位置（用于裁剪框计算）
      this.setData({
        imageRect: { left: imageLeft, top: imageTop, width: displayWidth, height: displayHeight },
        imagePosition: { 
          left: 0, // 相对于容器
          top: 0,  // 相对于容器
          width: containerWidth, 
          height: containerHeight 
        },
        imageInfo: { width, height },
        originalImageWidth: width,
        originalImageHeight: height,
        rotateAngle: 0,
        imageScale: 1,
        containerRect: rect || { left: 0, top: 0, width: containerWidth, height: containerHeight }
      }, () => {
        // 图片加载后若处于裁剪模式，重新初始化裁剪框
        if (this.data.isCropping) {
          const newCropBox = this.calculateInitialCropBox();
          if (newCropBox.width > 0 && newCropBox.height > 0) {
            this.setData({ cropBox: newCropBox });
          }
        }
      });
    }).exec();

    // 初始化马赛克画布
    if (this.data.currentTool === 'mosaic' || this.data.currentTool === 'eraser') {
      this.initMosaicCanvas();
    }
  },

  initMosaicCanvas() {
    return new Promise((resolve, reject) => {
      const query = wx.createSelectorQuery().in(this);
      query.select('#mosaicCanvas')
        .fields({ node: true, size: true })
        .exec((res) => {
          if (!res || res.length === 0 || !res[0]) {
            reject('未找到 Canvas 元素');
            return;
          }
          const canvasNode = res[0].node;
          const ctx = canvasNode.getContext('2d');
          const { width, height } = this.data.imagePosition;
          canvasNode.width = width;
          canvasNode.height = height;
          this.setData({
            canvasContext: ctx,
            canvas: canvasNode,
            canvasWidth: width,
            canvasHeight: height,
            isCanvasInit: true
          }, () => {
            // 初始化后重新渲染马赛克
            this.reRenderMosaic();
            resolve();
          });
        });
    });
  },

  toggleCropMode() {
    this.setData({
      isCropping: !this.data.isCropping,
      currentTool: ''
    }, () => {
      // 切换裁剪模式后，若开启裁剪则重新初始化裁剪框
      if (this.data.isCropping) {
        // 先获取容器位置，确保 imagePosition 已更新
        this.updateContainerRect().then(() => {
          const newCropBox = this.calculateInitialCropBox();
          if (newCropBox.width > 0 && newCropBox.height > 0) {
            this.setData({ cropBox: newCropBox });
          }
        });
      }
    });
  },

  // 开始拖动角点（优化版本，使用缓存的容器位置）
  startCropDrag(e) {
    if (!this.data.isCropping) return;
    
    const handle = e.currentTarget.dataset.handle;
    if (!handle) {
      console.warn('未找到 handle 属性:', e.currentTarget);
      return;
    }
    
    const touch = e.touches[0];
    if (!touch || !touch.clientX || !touch.clientY) {
      console.warn('触摸事件无效:', touch);
      return;
    }
    
    const { containerRect, cropBox } = this.data;
    
    // 保存触摸坐标，避免异步回调中失效
    const touchX = touch.clientX;
    const touchY = touch.clientY;
    
    // 优先使用缓存的容器位置，避免异步延迟
    if (containerRect && containerRect.left !== undefined && containerRect.top !== undefined) {
      const relativeX = touchX - containerRect.left;
      const relativeY = touchY - containerRect.top;
      
      this.setData({
        cropStartPos: {
          x: touchX,
          y: touchY,
          relativeX: relativeX,
          relativeY: relativeY,
          cropX: cropBox?.left || 0,
          cropY: cropBox?.top || 0,
          cropRight: cropBox?.right || 0,
          cropBottom: cropBox?.bottom || 0
        },
        draggingHandle: handle,
        isMovingCropBox: false
      });
      console.log(`开始拖动角点: ${handle}`, { touchX, touchY, relativeX, relativeY, cropBox });
      return;
    }
    
    // 如果没有缓存的容器位置，使用估算值并立即响应，同时异步更新
    const systemInfo = this.data.systemInfo || wx.getSystemInfoSync();
    const estimatedRect = {
      left: 0,
      top: 0,
      width: systemInfo.windowWidth || 375,
      height: systemInfo.windowHeight || 667
    };
    
    const relativeX = touchX - estimatedRect.left;
    const relativeY = touchY - estimatedRect.top;
    
    // 立即设置拖动状态，使用估算的容器位置
    this.setData({
      cropStartPos: {
        x: touchX,
        y: touchY,
        relativeX: relativeX,
        relativeY: relativeY,
        cropX: cropBox?.left || 0,
        cropY: cropBox?.top || 0,
        cropRight: cropBox?.right || 0,
        cropBottom: cropBox?.bottom || 0
      },
      draggingHandle: handle,
      isMovingCropBox: false,
      containerRect: estimatedRect // 临时使用估算值
    });
    
    console.log(`开始拖动角点: ${handle} (使用估算位置)`, { touchX, touchY, relativeX, relativeY, cropBox });
    
    // 异步获取准确的容器位置，用于后续拖动
    const query = wx.createSelectorQuery().in(this);
    query.select('.image-container').boundingClientRect((rect) => {
      if (rect) {
        this.setData({ containerRect: rect });
        console.log('容器位置已更新:', rect);
      }
    }).exec();
  },

  // 处理裁剪框拖动（优化版本，确保容器位置可用）
  onCropTouchMove(e) {
    if (!this.data.isCropping || !this.data.cropStartPos) return;
    
    const touch = e.touches[0];
    const { cropBox, imagePosition, containerRect } = this.data;
    
    if (!cropBox || !imagePosition) return;
    
    // 获取容器位置（优先使用缓存的）
    let currentRect = containerRect;
    if (!currentRect) {
      // 如果没有缓存的，使用默认值（基于系统信息估算）
      const systemInfo = this.data.systemInfo || wx.getSystemInfoSync();
      currentRect = {
        left: 0,
        top: 0,
        width: systemInfo.windowWidth || 375,
        height: systemInfo.windowHeight || 667
      };
      // 异步更新容器位置（用于下次使用）
      const query = wx.createSelectorQuery().in(this);
      query.select('.image-container').boundingClientRect((rect) => {
        if (rect) {
          this.setData({ containerRect: rect });
        }
      }).exec();
    }
    
    // 直接使用clientX/clientY计算相对坐标
    const relativeX = touch.clientX - currentRect.left;
    const relativeY = touch.clientY - currentRect.top;
    
    const maxWidth = imagePosition.width;
    const maxHeight = imagePosition.height;
    const minCropSize = 60; // 最小裁剪尺寸
    
    let newCropBox = { ...cropBox };
    
    // 拖动整个裁剪框（参考avatar-edit: touch.clientX - cropSize / 2）
    if (this.data.isMovingCropBox) {
      // 参考avatar-edit的简单计算方式
      const deltaX = relativeX - (this.data.cropStartPos.relativeX || 0);
      const deltaY = relativeY - (this.data.cropStartPos.relativeY || 0);
      
      let newX = (this.data.cropStartPos.cropX || cropBox.left) + deltaX;
      let newY = (this.data.cropStartPos.cropY || cropBox.top) + deltaY;
      
      // 参考avatar-edit的边界检查：Math.max(0, Math.min(newX, canvasWidth - cropSize))
      newX = Math.max(0, Math.min(newX, maxWidth - cropBox.width));
      newY = Math.max(0, Math.min(newY, maxHeight - cropBox.height));
      
      newCropBox.left = newX;
      newCropBox.top = newY;
      newCropBox.right = newX + cropBox.width;
      newCropBox.bottom = newY + cropBox.height;
      
    // 调整裁剪框大小（4个角点自由拖动）
    } else if (this.data.draggingHandle) {
      const handle = this.data.draggingHandle;
      
      // 验证 handle 是否有效
      if (!handle || !['top-left', 'top-right', 'bottom-left', 'bottom-right'].includes(handle)) {
        console.warn('无效的拖动角点:', handle);
        return;
      }
      
      // 获取初始裁剪框位置（从 cropStartPos 中获取，确保使用拖动开始时的位置）
      const startCropX = this.data.cropStartPos?.cropX ?? cropBox.left;
      const startCropY = this.data.cropStartPos?.cropY ?? cropBox.top;
      const startCropRight = this.data.cropStartPos?.cropRight ?? cropBox.right;
      const startCropBottom = this.data.cropStartPos?.cropBottom ?? cropBox.bottom;
      
      // 获取初始触摸位置
      const startRelativeX = this.data.cropStartPos?.relativeX ?? relativeX;
      const startRelativeY = this.data.cropStartPos?.relativeY ?? relativeY;
      
      // 计算相对于初始触摸点的偏移量
      const deltaX = relativeX - startRelativeX;
      const deltaY = relativeY - startRelativeY;
      
      // 根据拖动的角点调整裁剪框
      switch (handle) {
        case 'top-left':
          // 左上角：调整 left 和 top，保持右下角不变
          newCropBox.left = Math.max(0, Math.min(startCropX + deltaX, startCropRight - minCropSize));
          newCropBox.top = Math.max(0, Math.min(startCropY + deltaY, startCropBottom - minCropSize));
          newCropBox.right = startCropRight;
          newCropBox.bottom = startCropBottom;
          break;
        case 'top-right':
          // 右上角：调整 right 和 top，保持左下角不变
          newCropBox.right = Math.max(startCropX + minCropSize, Math.min(startCropRight + deltaX, maxWidth));
          newCropBox.top = Math.max(0, Math.min(startCropY + deltaY, startCropBottom - minCropSize));
          newCropBox.left = startCropX;
          newCropBox.bottom = startCropBottom;
          break;
        case 'bottom-left':
          // 左下角：调整 left 和 bottom，保持右上角不变
          newCropBox.left = Math.max(0, Math.min(startCropX + deltaX, startCropRight - minCropSize));
          newCropBox.bottom = Math.max(startCropY + minCropSize, Math.min(startCropBottom + deltaY, maxHeight));
          newCropBox.right = startCropRight;
          newCropBox.top = startCropY;
          break;
        case 'bottom-right':
          // 右下角：调整 right 和 bottom，保持左上角不变
          newCropBox.right = Math.max(startCropX + minCropSize, Math.min(startCropRight + deltaX, maxWidth));
          newCropBox.bottom = Math.max(startCropY + minCropSize, Math.min(startCropBottom + deltaY, maxHeight));
          newCropBox.left = startCropX;
          newCropBox.top = startCropY;
          break;
        default:
          console.warn('未知的拖动角点:', handle);
          return;
      }
      
      // 重新计算宽高
      newCropBox.width = newCropBox.right - newCropBox.left;
      newCropBox.height = newCropBox.bottom - newCropBox.top;
      
      // 确保最小尺寸
      if (newCropBox.width < minCropSize) {
        if (handle.includes('left')) {
          newCropBox.left = newCropBox.right - minCropSize;
        } else {
          newCropBox.right = newCropBox.left + minCropSize;
        }
        newCropBox.width = minCropSize;
      }
      if (newCropBox.height < minCropSize) {
        if (handle.includes('top')) {
          newCropBox.top = newCropBox.bottom - minCropSize;
        } else {
          newCropBox.bottom = newCropBox.top + minCropSize;
        }
        newCropBox.height = minCropSize;
      }
      
      // 最终边界检查：确保裁剪框完全在图片可视区域内
      // 如果超出左边界
      if (newCropBox.left < 0) {
        const offset = -newCropBox.left;
        newCropBox.left = 0;
        if (handle.includes('right')) {
          newCropBox.right = Math.min(newCropBox.right + offset, maxWidth);
        } else {
          newCropBox.right = Math.min(newCropBox.right - offset, maxWidth);
        }
      }
      // 如果超出上边界
      if (newCropBox.top < 0) {
        const offset = -newCropBox.top;
        newCropBox.top = 0;
        if (handle.includes('bottom')) {
          newCropBox.bottom = Math.min(newCropBox.bottom + offset, maxHeight);
        } else {
          newCropBox.bottom = Math.min(newCropBox.bottom - offset, maxHeight);
        }
      }
      // 如果超出右边界
      if (newCropBox.right > maxWidth) {
        const offset = newCropBox.right - maxWidth;
        newCropBox.right = maxWidth;
        if (handle.includes('left')) {
          newCropBox.left = Math.max(0, newCropBox.left - offset);
        } else {
          newCropBox.left = Math.max(0, newCropBox.left + offset);
        }
      }
      // 如果超出下边界
      if (newCropBox.bottom > maxHeight) {
        const offset = newCropBox.bottom - maxHeight;
        newCropBox.bottom = maxHeight;
        if (handle.includes('top')) {
          newCropBox.top = Math.max(0, newCropBox.top - offset);
        } else {
          newCropBox.top = Math.max(0, newCropBox.top + offset);
        }
      }
      
      // 重新计算宽高（边界调整后）
      newCropBox.width = newCropBox.right - newCropBox.left;
      newCropBox.height = newCropBox.bottom - newCropBox.top;
    } else {
      return;
    }
    
    // 更新裁剪框
    this.setData({ cropBox: newCropBox });
  },

  // 裁剪框拖动结束（参考avatar-edit的简单实现）
  onCropTouchEnd(e) {
    this.setData({
      cropStartPos: null,
      draggingHandle: null,
      isMovingCropBox: false
    });
  },

  // 应用裁剪（裁剪完成后直接上传，不预览）
  async applyCrop() {
    const { cropBox, currentPhotoPath, imageInfo, imagePosition } = this.data;

    if (!imagePosition || !imagePosition.width || !imagePosition.height || !imageInfo) {
      wx.showToast({
        title: '图片信息不完整',
        icon: 'none'
      });
      return;
    }

    if (!cropBox || !cropBox.width || !cropBox.height) {
      wx.showToast({
        title: '裁剪框无效',
        icon: 'none'
      });
      return;
    }

    wx.showLoading({
      title: '裁剪中...',
      mask: true
    });

    // 参考avatar-edit：使用页面中的canvas进行裁剪
    const query = wx.createSelectorQuery().in(this);
    query.select('#mergeCanvas')
      .fields({ node: true, size: true })
      .exec((res) => {
        if (!res || !res[0] || !res[0].node) {
          wx.hideLoading();
          wx.showToast({
            title: 'Canvas初始化失败',
            icon: 'none'
          });
          return;
        }

        const canvas = res[0].node;
        const ctx = canvas.getContext('2d');

        // 参考avatar-edit：计算裁剪区域在原图中的比例
        const scaleX = imageInfo.width / imagePosition.width;
        const scaleY = imageInfo.height / imagePosition.height;
        
        // 参考avatar-edit：转换为原始图片的实际像素坐标
        const sourceX = Math.max(0, cropBox.left * scaleX);
        const sourceY = Math.max(0, cropBox.top * scaleY);
        const sourceWidth = Math.max(1, Math.min(cropBox.width * scaleX, imageInfo.width - sourceX));
        const sourceHeight = Math.max(1, Math.min(cropBox.height * scaleY, imageInfo.height - sourceY));

        // 设置Canvas尺寸为裁剪大小
        const canvasWidth = Math.ceil(sourceWidth);
        const canvasHeight = Math.ceil(sourceHeight);
        canvas.width = canvasWidth;
        canvas.height = canvasHeight;

        console.log('裁剪参数:', {
          cropBox,
          imageInfo,
          imagePosition,
          scaleX,
          scaleY,
          sourceX,
          sourceY,
          sourceWidth,
          sourceHeight,
          canvasWidth,
          canvasHeight
        });

        // 加载图片
        const img = canvas.createImage();
        
        img.onerror = (err) => {
          wx.hideLoading();
          console.error('图片加载失败:', err);
          wx.showToast({
            title: '图片加载失败',
            icon: 'none'
          });
        };

        img.onload = () => {
          try {
            // 参考avatar-edit：仅绘制裁剪选中的区域
            // drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
            ctx.drawImage(
              img,
              sourceX,        // 原始图片中裁剪区域的起点X
              sourceY,        // 原始图片中裁剪区域的起点Y
              sourceWidth,    // 原始图片中裁剪区域的宽度
              sourceHeight,   // 原始图片中裁剪区域的高度
              0, 0,           // 画布上的起点坐标
              canvasWidth,    // 画布上的宽度
              canvasHeight    // 画布上的高度
            );

            // 导出图片并直接上传
            wx.canvasToTempFilePath({
              canvas: canvas,
              success: async (res) => {
                try {
                  // 验证文件
                  const fileInfo = await new Promise((resolve, reject) => {
                    wx.getFileInfo({
                      filePath: res.tempFilePath,
                      success: resolve,
                      fail: reject
                    });
                  });

                  if (!fileInfo || !fileInfo.size || fileInfo.size === 0) {
                    throw new Error('裁剪后的文件无效');
                  }

                  // 裁剪完成，直接上传（不预览）
                  wx.hideLoading();
                  wx.showLoading({
                    title: '上传中...',
                    mask: true
                  });

                  // 调用原有的上传方法
                  const uploadResult = await cosManager.upload(res.tempFilePath, {
                    fileType: 'image',
                    enableDedup: false,
                    onProgress: (percent) => {
                      wx.showLoading({
                        title: `上传中 ${Math.round(percent)}%`,
                        mask: true
                      });
                    },
                    enableCompress: false,
                    compressOptions: {
                      maxWidth: 400,
                      maxHeight: 400,
                      targetSize: 20 * 1024
                    }
                  });

                  if (!uploadResult || !uploadResult.success || !uploadResult.fileUrl) {
                    throw new Error(uploadResult?.error || uploadResult?.message || '上传失败');
                  }

                  wx.hideLoading();

                  // 跳转到edits页面
                  wx.redirectTo({
                    url: `/subpackages/media/edits/edits?imagePath=${encodeURIComponent(uploadResult.fileUrl)}`,
                    fail: (err) => {
                      console.error('跳转发布页失败:', err);
                      wx.showToast({
                        title: '跳转失败，请重试',
                        icon: 'none',
                        duration: 2000
                      });
                    }
                  });
                } catch (error) {
                  wx.hideLoading();
                  console.error('裁剪上传失败:', error);
                  wx.showToast({
                    title: error.message || '裁剪上传失败，请重试',
                    icon: 'none',
                    duration: 2000
                  });
                }
              },
              fail: (err) => {
                wx.hideLoading();
                console.error('生成裁剪图片失败:', err);
                wx.showToast({
                  title: '生成图片失败',
                  icon: 'none'
                });
              }
            }, this);
          } catch (error) {
            wx.hideLoading();
            console.error('绘制裁剪图片失败:', error, error.stack);
            wx.showToast({
              title: '绘制失败: ' + (error.message || '未知错误'),
              icon: 'none',
              duration: 3000
            });
          }
        };

        img.src = currentPhotoPath;
      });
  },

  // 旋转
  rotateImage() {
    // 如果正在裁剪，先关闭裁剪模式
    if (this.data.isCropping) {
      this.setData({ isCropping: false, currentTool: '' });
    }
    
    let { rotateAngle, cropBox, imageRect, mosaicData, imagePosition } = this.data;

    // 计算新旋转角度
    const newRotateAngle = (rotateAngle - 90) % 360;
    const widthRatio = cropBox.width / imageRect.width;
    const heightRatio = cropBox.height / imageRect.height;
    const newWidth = cropBox.height;
    const newHeight = cropBox.width;
    const newLeft = imageRect.left + (imageRect.width - newWidth) / 2;
    const newTop = imageRect.top + (imageRect.height - newHeight) / 2;

    // 旋转历史马赛克坐标
    const centerX = imagePosition.width / 2;
    const centerY = imagePosition.height / 2;
    const rad = -90 * Math.PI / 180;
    const cos = Math.cos(rad);
    const sin = Math.sin(rad);
    const rotatedMosaicData = mosaicData.map(point => {
      // 转换为相对图片中心的坐标
      const x = point.x - centerX;
      const y = point.y - centerY;
      // 旋转坐标
      const rotatedX = x * cos - y * sin + centerX;
      const rotatedY = x * sin + y * cos + centerY;
      return { ...point, x: rotatedX, y: rotatedY };
    });

    // 更新数据
    this.setData({
      rotateAngle: newRotateAngle,
      isRotated: true,
      hasEdits: true,
      cropBox: { left: newLeft, top: newTop, width: newWidth, height: newHeight, right: newLeft + newWidth, bottom: newTop + newHeight },
      mosaicData: rotatedMosaicData
    }, () => {
      // 重新渲染马赛克
      this.reRenderMosaic();
    });
  },

  // 重新渲染马赛克
  reRenderMosaic() {
    const { canvasContext, mosaicData, canvasWidth, canvasHeight } = this.data;
    if (!canvasContext) return;

    // 清空 Canvas 原有内容
    canvasContext.clearRect(0, 0, canvasWidth, canvasHeight);
    // 重新绘制所有马赛克
    mosaicData.forEach(point => {
      canvasContext.save();
      canvasContext.fillStyle = 'rgba(128, 128, 128, 0.8)';
      canvasContext.beginPath();
      canvasContext.arc(point.x, point.y, point.size / 2, 0, 2 * Math.PI);
      canvasContext.fill();
      canvasContext.restore();
    });
  },

  // 合并图片（支持裁剪后的图片）
  async mergeImages() {
    return new Promise((resolve, reject) => {
      try {
        const { currentPhotoPath, imageInfo, rotateAngle, mosaicData, systemInfo } = this.data;

        // 验证必要数据
        if (!currentPhotoPath) {
          reject(new Error('图片路径不存在'));
          return;
        }

        if (!imageInfo || !imageInfo.width || !imageInfo.height) {
          reject(new Error('图片信息不完整'));
          return;
        }

        if (!systemInfo || !systemInfo.windowWidth || !systemInfo.windowHeight) {
          reject(new Error('系统信息不完整'));
          return;
        }

        // 获取页面内的辅助 Canvas 节点
        const query = wx.createSelectorQuery().in(this);
        query.select('#mergeCanvas')
          .fields({ node: true, size: true })
          .exec((res) => {
            if (!res || res.length === 0 || !res[0] || !res[0].node) {
              reject(new Error('未找到辅助 Canvas 节点'));
              return;
            }

            const mergeCanvas = res[0].node;
            const mergeCtx = mergeCanvas.getContext('2d');

            // 直接使用当前图片的原始尺寸（裁剪后已经是最终尺寸）
            const canvasWidth = imageInfo.width;
            const canvasHeight = imageInfo.height;
            
            // 设置 Canvas 尺寸为图片原始尺寸
            mergeCanvas.width = canvasWidth;
            mergeCanvas.height = canvasHeight;

            console.log('合并图片参数:', {
              currentPhotoPath,
              imageInfo,
              rotateAngle,
              mosaicDataLength: mosaicData?.length || 0,
              canvasWidth,
              canvasHeight
            });

            // 加载图片并绘制
            const img = mergeCanvas.createImage();
            
            // 设置超时，避免图片加载卡死
            const timeoutId = setTimeout(() => {
              reject(new Error('图片加载超时'));
            }, 10000); // 10秒超时

            img.onload = () => {
              clearTimeout(timeoutId);
              
              try {
                // 清空画布
                mergeCtx.clearRect(0, 0, canvasWidth, canvasHeight);

                // 绘制旋转后的图片
                mergeCtx.save();
                mergeCtx.translate(canvasWidth / 2, canvasHeight / 2);
                mergeCtx.rotate(rotateAngle * Math.PI / 180);
                mergeCtx.drawImage(
                  img,
                  -canvasWidth / 2,
                  -canvasHeight / 2,
                  canvasWidth,
                  canvasHeight
                );
                mergeCtx.restore();

                // 如果有马赛克，绘制马赛克（需要根据图片尺寸比例调整坐标）
                if (mosaicData && mosaicData.length > 0) {
                  // 计算缩放比例（从显示尺寸到原始尺寸）
                  const imagePosition = this.data.imagePosition || {};
                  let scaleX = 1;
                  let scaleY = 1;
                  
                  if (imagePosition.width && imagePosition.height) {
                    scaleX = canvasWidth / imagePosition.width;
                    scaleY = canvasHeight / imagePosition.height;
                  }

                  mosaicData.forEach(point => {
                    mergeCtx.fillStyle = 'rgba(128, 128, 128, 0.8)';
                    mergeCtx.beginPath();
                    mergeCtx.arc(
                      point.x * scaleX,
                      point.y * scaleY,
                      (point.size / 2) * scaleX,
                      0,
                      2 * Math.PI
                    );
                    mergeCtx.fill();
                  });
                }

                // 导出图片
                wx.canvasToTempFilePath({
                  canvas: mergeCanvas,
                  x: 0,
                  y: 0,
                  width: canvasWidth,
                  height: canvasHeight,
                  destWidth: canvasWidth,
                  destHeight: canvasHeight,
                  success: (res) => {
                    console.log('合并图片成功:', res.tempFilePath);
                    resolve(res.tempFilePath);
                  },
                  fail: (err) => {
                    console.error('Canvas 导出临时路径失败:', err);
                    reject(new Error('导出图片失败: ' + (err.errMsg || '未知错误')));
                  }
                }, this);
              } catch (error) {
                clearTimeout(timeoutId);
                console.error('绘制图片失败:', error);
                reject(new Error('绘制图片失败: ' + (error.message || '未知错误')));
              }
            };

            img.onerror = (err) => {
              clearTimeout(timeoutId);
              console.error('图片加载失败:', err, currentPhotoPath);
              reject(new Error('图片加载失败: ' + (err.errMsg || '未知错误')));
            };

            img.src = currentPhotoPath;
          });
      } catch (error) {
        console.error('合并图片异常:', error);
        reject(new Error('合并图片失败: ' + (error.message || '未知错误')));
      }
    });
  },

  cancelCrop() {
    this.setData({ 
      isCropping: false,
      currentTool: ''
    });
  },

  selectTool(e) {
    // 获取点击的工具
    const tool = e.currentTarget.dataset.tool;
    const currentActiveTool = this.data.currentTool;

    // 判断是否为"第二次点击"
    if (currentActiveTool === tool) {
      // 第二次点击：取消激活，清空工具状态
      this.setData({
        // 清空当前工具
        currentTool: '',
        // 同步关闭裁剪
        isCropping: false,
      });
      return;
    }

    // 裁剪工具特殊处理
    if (tool === 'crop') {
      this.setData({
        currentTool: 'crop',
        isCropping: !this.data.isCropping
      }, () => {
        // 切换裁剪模式后，若开启裁剪则重新初始化裁剪框
        if (this.data.isCropping) {
          // 先获取容器位置
          this.updateContainerRect().then(() => {
            // 在 setData 回调中初始化，确保 imagePosition 已更新
            setTimeout(() => {
              const newCropBox = this.calculateInitialCropBox();
              if (newCropBox.width > 0 && newCropBox.height > 0) {
                this.setData({
                  cropBox: newCropBox
                });
              }
            }, 50);
          });
        }
      });
      return;
    }

    // 第一次点击：激活工具，初始化 Canvas
    this.setData({
      currentTool: tool,
      isCropping: false
    }, async () => {
      if (tool === 'mosaic' || tool === 'eraser') {
        await this.initMosaicCanvas();
        // 重新绘制所有马赛克
        const { canvasContext, mosaicData } = this.data;
        if (canvasContext && mosaicData.length > 0) {
          canvasContext.clearRect(0, 0, this.data.canvasWidth, this.data.canvasHeight);
          mosaicData.forEach(point => {
            canvasContext.fillStyle = 'rgba(128, 128, 128, 0.8)';
            canvasContext.beginPath();
            canvasContext.arc(point.x, point.y, point.size / 2, 0, 2 * Math.PI);
            canvasContext.fill();
          });
        }
      }
    });
  },

  onSizeTouchStart(e) {
    this.setData({
      dragStartX: e.touches[0].clientX
    });
  },

  onSizeTouchMove(e) {
    const query = wx.createSelectorQuery().in(this);
    query.select('.mosaic-size-drag')
      .boundingClientRect((rect) => {
        if (!rect) return;

        const containerWidth = rect.width;
        const touchX = e.touches[0].clientX;
        const startX = rect.left;
        const endX = rect.right;

        // 计算滑块在容器内的百分比
        let percent = ((touchX - startX) / containerWidth) * 100;
        percent = Math.max(0, Math.min(100, percent)); // 限制在0-100

        // 计算马赛克大小
        const newSize = 5 + (percent / 100) * 25;

        this.setData({
          mosaicSize: newSize,
          thumbStyle: { left: `${percent}%` }
        });
      })
      .exec();
  },

  onCanvasTouchStart(e) {
    const { currentTool } = this.data;
    if (currentTool === 'mosaic' || currentTool === 'eraser') {
      this.handleCanvasDrawing(e);
    }
  },

  onCanvasTouchMove(e) {
    const { currentTool } = this.data;
    if (currentTool === 'mosaic' || currentTool === 'eraser') {
      this.handleCanvasDrawing(e);
    }
  },

  onCanvasTouchEnd() {
    // 触摸结束无需处理
  },

  // 画布绘制逻辑
  handleCanvasDrawing(e) {
    const {
      currentTool, canvasContext, mosaicSize, mosaicData,
      imagePosition
    } = this.data;

    if (!canvasContext || !imagePosition) return;

    // 获取触摸点原始坐标
    const touch = e.touches[0];
    const rawX = touch.clientX;
    const rawY = touch.clientY;

    // Canvas在页面中的实际位置
    const query = wx.createSelectorQuery().in(this);
    query.select('#mosaicCanvas')
      .boundingClientRect()
      .exec((res) => {
        if (res && res[0]) {
          const canvasRect = res[0];

          // 计算相对于Canvas的触摸坐标
          const canvasX = rawX - canvasRect.left;
          const canvasY = rawY - canvasRect.top;

          // 计算Canvas的逻辑尺寸与物理尺寸的比例
          const realWidth = this.data.canvasWidth || imagePosition.width;
          const realHeight = this.data.canvasHeight || imagePosition.height;
          const scaleX = realWidth / canvasRect.width;
          const scaleY = realHeight / canvasRect.height;

          // 计算最终绘制坐标
          const drawX = canvasX * scaleX;
          const drawY = canvasY * scaleY;

          // 绘制马赛克或橡皮擦效果
          if (currentTool === 'mosaic') {
            const newMosaicData = [...mosaicData, { x: drawX, y: drawY, size: mosaicSize }];
            canvasContext.save();
            canvasContext.fillStyle = 'rgba(128, 128, 128, 0.8)';
            canvasContext.beginPath();
            canvasContext.arc(drawX, drawY, mosaicSize / 2, 0, 2 * Math.PI);
            canvasContext.fill();
            canvasContext.restore();
            this.setData({ mosaicData: newMosaicData, hasMosaic: true, hasEdits: true });
          } else if (currentTool === 'eraser') {
            const newMosaicData = mosaicData.filter(point => {
              const distance = Math.hypot(drawX - point.x, drawY - point.y);
              return distance > (point.size + mosaicSize) / 2;
            });
            canvasContext.clearRect(0, 0, realWidth, realHeight);
            newMosaicData.forEach(point => {
              canvasContext.save();
              canvasContext.fillStyle = 'rgba(128, 128, 128, 0.8)';
              canvasContext.beginPath();
              canvasContext.arc(point.x, point.y, point.size / 2, 0, 2 * Math.PI);
              canvasContext.fill();
              canvasContext.restore();
            });
            this.setData({ mosaicData: newMosaicData, hasMosaic: newMosaicData.length > 0, hasEdits: true });
          }
        }
      });
  },

  clearMosaic() {
    this.initMosaicCanvas();
    this.setData({
      mosaicData: [],
      hasMosaic: false,
      hasEdits: this.data.rotateAngle !== 0 || this.data.cropBox.width !== this.calculateInitialCropBox(this.data.imageInfo).width
    });
  },

  restoreOriginal() {
    // 如果正在裁剪，先关闭裁剪模式
    if (this.data.isCropping) {
      this.setData({ isCropping: false, currentTool: '' });
    }
    
    const currentScale = this.data.imageScale;

    wx.getImageInfo({
      src: this.data.originalPhotoPath,
      success: (info) => {
        this.setData({
          currentPhotoPath: this.data.originalPhotoPath,
          imageInfo: info,
          rotateAngle: 0,
          imageScale: currentScale,
          mosaicData: [],
          hasMosaic: false,
          hasEdits: false,
          isCropping: false,
          currentTool: '',
          cropBox: this.calculateInitialCropBox(info),
          isRotated: false
        }, () => {
          this.initMosaicCanvas();
        });
      }
    });
  },

  retryPhoto() {
    this.setData({
      hasTakenPhoto: false,
      currentTool: '',
      isCropping: false
    });
  },

  // 添加裁剪逻辑
  async confirmPhoto() {
    // 显示加载提示
    wx.showLoading({ 
      title: '处理中...', 
      mask: true 
    });

    try {
      // 合并图片
      let tempFilePath;
      try {
        tempFilePath = await this.mergeImages();
      } catch (mergeError) {
        wx.hideLoading();
        console.error('合并图片失败:', mergeError);
        wx.showToast({
          title: '图片处理失败',
          icon: 'none',
          duration: 2000
        });
        return;
      }
      
      if (!tempFilePath) {
        wx.hideLoading();
        wx.showToast({
          title: '图片处理失败',
          icon: 'none',
          duration: 2000
        });
        return;
      }

      // 上传图片
      try {
        const uploadResult = await cosManager.upload(tempFilePath, {
          fileType: 'image',
          enableDedup: false,
          onProgress: (percent) => {
            console.log('上传进度:', percent + '%');
            // 更新加载提示
            wx.showLoading({ 
              title: `上传中 ${Math.round(percent)}%`, 
              mask: true 
            });
          },
          enableCompress: false,
          compressOptions: {
            maxWidth: 400,
            maxHeight: 400,
            targetSize: 20 * 1024
          }
        });

        // 检查上传结果
        if (!uploadResult || !uploadResult.success) {
          throw new Error(uploadResult?.error || uploadResult?.message || '上传失败');
        }

        if (!uploadResult.fileUrl) {
          throw new Error('上传失败：未获取到文件URL');
        }

        // 获取图片路径
        const imagePath = uploadResult.fileUrl;

        // 确保隐藏loading，避免页面切换时残留
        wx.hideLoading();

        // 跳转发布页并传递图片数据（不显示toast，避免与页面切换冲突）
        wx.redirectTo({
          url: `/subpackages/media/edits/edits?imagePath=${encodeURIComponent(imagePath)}`,
          fail: (err) => {
            console.error('跳转发布页失败:', err);
            wx.showToast({ 
              title: '跳转失败，请重试', 
              icon: 'none', 
              duration: 2000 
            });
          }
        });
      } catch (uploadError) {
        wx.hideLoading();
        console.error('上传失败:', uploadError);
        
        // 判断错误类型，提供更友好的提示
        let errorMessage = '上传失败，请检查网络后重试';
        if (uploadError && uploadError.message) {
          if (uploadError.message.includes('Failed to fetch') || 
              uploadError.message.includes('网络') ||
              uploadError.message.includes('timeout')) {
            errorMessage = '网络连接失败，请检查网络后重试';
          } else if (uploadError.message.includes('权限') || 
                     uploadError.message.includes('AccessDenied')) {
            errorMessage = '上传权限不足，请重新登录';
          } else {
            errorMessage = uploadError.message || errorMessage;
          }
        }

        wx.showModal({
          title: '上传失败',
          content: errorMessage,
          showCancel: true,
          cancelText: '取消',
          confirmText: '重试',
          success: (res) => {
            if (res.confirm) {
              // 用户选择重试
              this.confirmPhoto();
            }
          }
        });
        return; // 确保不再执行后续代码
      }
    } catch (err) {
      wx.hideLoading();
      console.error('图片处理失败:', err);
      
      let errorMessage = '图片处理失败，请重试';
      if (err && err.message) {
        errorMessage = err.message;
      }

      wx.showToast({
        title: errorMessage,
        icon: 'none',
        duration: 2000
      });
    }
  },


  navigateBack() {
    wx.navigateBack({
      // 返回上一页
      delta: 1
    });
  },

  saveAndReturn(imagePath) {
    const pages = getCurrentPages();
    const prevPage = pages[pages.length - 2];
    if (prevPage && prevPage.uploadImage) {
      prevPage.uploadImage(imagePath);
    }

    this.navigateBack();
  },

  goBackToShoot() {
    wx.redirectTo({
      url: '/subpackages/media/camera/camera',
      success: () => {

      },
      fail: (err) => {
        console.error("返回拍摄页面失败：", err);
        wx.showToast({ title: '返回失败，请重试', icon: 'none' });
      }
    });
  },

  handleCameraError(e) {
    console.error('相机错误:', e.detail);
    const error = e.detail;
    
    // 处理权限相关的错误
    if (error.errMsg && (error.errMsg.includes('permission') || error.errMsg.includes('权限'))) {
      wx.showModal({
        title: '权限不足',
        content: '请授予相机权限以使用拍摄功能',
        confirmText: '去设置',
        cancelText: '取消',
        success: (modalRes) => {
          if (modalRes.confirm) {
            wx.openSetting({
              success: (settingRes) => {
                // 如果用户在设置中授权了，可以尝试重新加载页面
                if (settingRes.authSetting['scope.camera']) {
                  // 权限已授予，可以继续使用相机
                  console.log('用户已授予相机权限');
                } else {
                  // 用户仍未授权，返回上一页
                  this.navigateBack();
                }
              },
              fail: () => {
                this.navigateBack();
              }
            });
          } else {
            // 用户取消，返回上一页
            this.navigateBack();
          }
        }
      });
    } else {
      // 其他相机错误
      wx.showToast({
        title: '相机初始化失败',
        icon: 'none'
      });

      setTimeout(() => {
        this.navigateBack();
      }, 1500);
    }
  }
});
