<template>

  <u-popup v-model="visible" mode="center" width="85%" border-radius="16" :mask-close-able="false">

    <view class="popup-wrap">

      <view class="popup-title">图片较大</view>

      <view v-if="sizeText" class="size-text">{{ sizeText }}</view>



      <view v-if="status === 'compressing'" class="compressing-panel">

        <image

          v-if="originalPath"

          :src="originalPath"

          mode="aspectFit"

          class="preview-image single"

          @click="previewImage(originalPath)"

        />

        <text v-if="originalPath" class="preview-hint">点击预览</text>

        <view class="compressing-status">

          <u-loading mode="circle" />

          <text class="progress-text">{{ progressText }}</text>

        </view>

      </view>



      <view v-else-if="status === 'ready'" class="compare-panel">

        <view class="preview-column">

          <text class="preview-label">原图</text>

          <image

            :src="originalPath"

            mode="aspectFit"

            class="preview-image"

            @click="previewImage(originalPath)"

          />

          <text class="preview-size">{{ formatFileSize(originalSize) }}</text>

          <text class="preview-hint">点击预览</text>

        </view>

        <view class="preview-column">

          <text class="preview-label">压缩后</text>

          <image

            :src="compressedPath"

            mode="aspectFit"

            class="preview-image"

            @click="previewImage(compressedPath)"

          />

          <text class="preview-size">{{ formatFileSize(compressedSize) }}</text>

          <text class="preview-hint">点击预览</text>

        </view>

      </view>



      <view v-else-if="status === 'gifSkipped'" class="gif-panel">

        <image

          v-if="originalPath"

          :src="originalPath"

          mode="aspectFit"

          class="preview-image single"

          @click="previewImage(originalPath)"

        />

        <text v-if="originalPath" class="preview-hint">点击预览</text>

        <text class="hint-text">GIF 不支持压缩，将上传原图。</text>

      </view>



      <view v-else class="error-panel">

        <image

          v-if="originalPath"

          :src="originalPath"

          mode="aspectFit"

          class="preview-image single"

          @click="previewImage(originalPath)"

        />

        <text v-if="originalPath" class="preview-hint">点击预览</text>

        <text class="error-text">{{ errorMessage }}</text>

      </view>



      <view class="footer-actions">

        <view class="btn btn-default" @click="finish('cancel')">取消</view>

        <view

          v-if="status === 'ready' || status === 'error'"

          class="btn btn-default"

          @click="finish('original')"

        >

          {{ originalButtonLabel }}

        </view>

        <view

          v-if="status === 'ready'"

          class="btn btn-primary"

          @click="finish('compressed')"

        >

          {{ compressedButtonLabel }}

        </view>

        <view

          v-if="status === 'gifSkipped'"

          class="btn btn-primary"

          @click="finish('original')"

        >

          {{ originalButtonLabel }}

        </view>

      </view>

    </view>

  </u-popup>

</template>



<script>

import {

  formatFileSize,

  formatSavingsPercent,

  isGifPath,

  tryCompressImage,

} from '@/common/js/image-compress.js';



export default {

  name: 'ImageCompressPopup',

  data() {

    return {

      visible: false,

      status: 'compressing',

      progressText: '正在压缩，请稍候…',

      errorMessage: '',

      originalPath: '',

      compressedPath: '',

      originalSize: 0,

      compressedSize: 0,

      skipped: false,

      resolver: null,

    };

  },

  computed: {

    sizeText() {

      if (!this.originalSize) return '';

      const originalText = formatFileSize(this.originalSize);

      if (this.status === 'gifSkipped') {

        return `原图 ${originalText}`;

      }

      if (this.compressedSize && this.status === 'ready') {

        const savings = formatSavingsPercent(this.originalSize, this.compressedSize);

        return `原图 ${originalText} → 压缩后 ${formatFileSize(this.compressedSize)}${savings}`;

      }

      if (this.compressedSize) {

        return `原图 ${originalText} → 压缩后 ${formatFileSize(this.compressedSize)}`;

      }

      return `原图 ${originalText}`;

    },

    originalButtonLabel() {

      if (!this.originalSize) return '使用原图';

      return `使用原图 (${formatFileSize(this.originalSize)})`;

    },

    compressedButtonLabel() {

      if (!this.compressedSize) return '使用压缩图';

      return `使用压缩图 (${formatFileSize(this.compressedSize)})`;

    },

  },

  methods: {

    formatFileSize,

    previewImage(current) {

      if (!this.originalPath) return;

      const urls =

        this.status === 'ready' && this.compressedPath

          ? [this.originalPath, this.compressedPath]

          : [this.originalPath];

      uni.previewImage({

        urls,

        current,

      });

    },

    open({ path, size }) {

      return new Promise((resolve) => {

        this.resolver = resolve;

        this.originalPath = path;

        this.originalSize = size;

        this.compressedPath = '';

        this.compressedSize = 0;

        this.skipped = false;

        this.errorMessage = '';

        this.progressText = '正在压缩，请稍候…';

        this.visible = true;

        this.startCompress(path, size);

      });

    },

    async startCompress(path, size) {

      if (isGifPath(path)) {

        this.skipped = true;

        this.status = 'gifSkipped';

        return;

      }



      this.status = 'compressing';

      this.progressText = '正在压缩（质量 80%）…';



      try {

        const compressed = await tryCompressImage(path, [80, 60, 40], (quality) => {

          this.progressText = `正在压缩（质量 ${quality}%）…`;

        });

        this.compressedPath = compressed.path;

        this.compressedSize = compressed.size;

        this.status = 'ready';

        this.progressText = '';

      } catch (error) {

        this.status = 'error';

        this.errorMessage = '图片压缩失败，请使用原图或取消';

        this.progressText = '';

      }

    },

    finish(choice) {

      const result = { choice, path: null, size: 0, usedCompress: false };



      if (choice === 'cancel') {

        this.visible = false;

        this.resolver && this.resolver(null);

        this.resolver = null;

        return;

      }



      if (choice === 'compressed' && this.status === 'ready') {

        result.path = this.compressedPath;

        result.size = this.compressedSize;

        result.usedCompress = true;

      } else {

        result.path = this.originalPath;

        result.size = this.originalSize;

        result.usedCompress = false;

      }



      this.visible = false;

      this.resolver && this.resolver(result);

      this.resolver = null;

    },

  },

};

</script>



<style lang="scss" scoped>

.popup-wrap {

  padding: 32rpx;

}



.popup-title {

  font-size: 32rpx;

  font-weight: 600;

  text-align: center;

  margin-bottom: 16rpx;

}



.size-text {

  font-size: 26rpx;

  color: #666;

  text-align: center;

  margin-bottom: 24rpx;

}



.preview-image {

  width: 100%;

  height: 280rpx;

  background: #fafafa;

  border-radius: 12rpx;

}



.preview-image.single {

  width: 100%;

}



.compare-panel {

  display: flex;

  gap: 16rpx;

}



.preview-column {

  flex: 1;

  display: flex;

  flex-direction: column;

  align-items: center;

}



.preview-label {

  font-size: 26rpx;

  font-weight: 500;

  margin-bottom: 12rpx;

}



.preview-size {

  margin-top: 8rpx;

  font-size: 22rpx;

  color: #999;

}



.preview-hint {

  margin-top: 4rpx;

  font-size: 22rpx;

  color: #bbb;

}



.compressing-panel,

.gif-panel,

.error-panel {

  display: flex;

  flex-direction: column;

  align-items: center;

  gap: 24rpx;

}



.compressing-status {

  display: flex;

  align-items: center;

  gap: 16rpx;

}



.progress-text,

.hint-text {

  font-size: 26rpx;

  color: #666;

}



.error-text {

  font-size: 26rpx;

  color: #fa3534;

}



.footer-actions {

  display: flex;

  justify-content: flex-end;

  flex-wrap: wrap;

  gap: 16rpx;

  margin-top: 32rpx;

}



.btn {

  min-width: 160rpx;

  padding: 16rpx 24rpx;

  border-radius: 8rpx;

  font-size: 26rpx;

  text-align: center;

}



.btn-default {

  background: #f5f5f5;

  color: #333;

}



.btn-primary {

  background: #2979ff;

  color: #fff;

}

</style>

