<template>
  <view class="ali-oss-uploader">
	<view class="preview-container" :style="'width:'+width">
	  <!-- 预览区域 -->
	  <view v-if="accept == 'image/*'" class="preview-container" :style="'width:'+width">
	  	<view
	  	  v-for="(file, index) in fileList" 
	  	  :key="index"
	  	  class="preview-item"
	  	>
	  	  <image
	  	    :src="file"
	  	    class="preview-image"
	  	    mode="aspectFill"
	  	    @click="handlePreview(index)"
	  	  />
	  	  <view v-if="deletable" class="delete-icon" @click.stop="handleDelete(index)">
	  	    ×
	  	  </view>
	  	</view>
		<!-- 上传按钮 -->
		<view class="preview-item">
			<view 
			  class="upload-btn"
			  @click="handleUpload"
			  :style="btnStyle"
			  v-if="fileList.length < maxCount"
			>
			  <slot name="button">
				<text class="plus-icon">+</text>
			  </slot>
			</view>
		</view>
		
	  </view>
	  
	  <!-- 视频预览区域 -->
	  <view class="preview-container" :style="'width:'+width" v-if="accept == 'video/*'">
	  	<view 
			class="preview-item"
			v-if="oneFile"
			>
			<!-- <video
			  :src="oneFile"
			  class="preview-image"
			  @click="handlePreview(index)"
			/> -->
			<image class="preview-image" :src="oneFile + '?x-oss-process=video/snapshot,t_0,f_jpg'" mode="aspectFill"></image>
			<view v-if="deletable" class="delete-icon" @click.stop="handleDelete()">
			  ×
			</view>
		</view>
		<view class="preview-item">
			<!-- 上传按钮 -->
			<view 
			  class="upload-btn"
			  @click="handleUpload"
			  :style="btnStyle"
			  v-if="!oneFile"
			>
			  <slot name="button">
			    <text class="plus-icon">+</text>
			  </slot>
			</view>
		</view>
	  </view>
	</view>
    <!-- 提示文字 -->
    <!-- <text v-if="tips" class="tips-text">{{ tips }}</text> -->
    
  </view>
</template>

<script>
import request from '../../utils/request'
import permissionUtils from '../../utils/per'
import locationService from '../../utils/locationService';
export default {
  name: 'AliOssUploader',
  
  props: {
    // 已上传文件列表
    value: {
      type: Array,
      default: () => []
    },
	// 单个上传文件
	fileString: {
	  type: String,
	  default: ''
	},
    // 按钮文字
    buttonText: {
      type: String,
      default: '上传图片'
    },
    // 提示文字
    tips: {
      type: String,
      default: ''
    },
    // 最大上传数量
    maxCount: {
      type: Number,
      default: 3
    },
    // 单个文件大小限制(MB)
    maxSize: {
      type: Number,
      default: 5
    },
    // 是否显示预览
    showPreview: {
      type: Boolean,
      default: true
    },
    // 是否可删除
    deletable: {
      type: Boolean,
      default: true
    },
    // 按钮自定义样式
    btnStyle: {
      type: Object,
      default: () => ({})
    },
    // 文件类型
    accept: {
      type: String,
      default: 'image/*'
    },
	// 当前用户id
	userId: {
	  type: Number,
	  default: null
	},
	width: {
	  type: String,
	  default: ''
	},
	type: {
	  type: Number,
	  default: null
	},
	kind: {
	  type: Number,
	  default: 1
	}
  },
  
  data() {
    return {
      fileList: [],
	  oneFile: '',
      loading: false
    }
  },
  
  watch: {
    value: {
      immediate: true,
      handler(newVal) {
        this.fileList = [...newVal]
      }
    },
	fileString: {
	  immediate: true,
	  handler(newVal) {
	    this.oneFile = newVal
	  }
	}
  },
  
  methods: {
	
	// 显示权限说明弹窗
	showPermissionDialog(title, content) {
	  return new Promise((resolve) => {
		uni.showModal({
		  title,
		  content,
		  confirmText: '去开启',
		  success(res) {
			resolve(res.confirm);
		  }
		});
	  });
	},
    // 触发上传
    async handleUpload() {
      const systemInfo = uni.getSystemInfoSync();
      const isIOS = systemInfo.platform === 'ios';

      // 弹出操作菜单
      const res = await new Promise((resolve, reject) => {
        uni.showActionSheet({
          itemList: ['拍照', '从相册选择'],
          success: resolve,
          fail: reject
        });
      }).catch(() => ({ tapIndex: -1 }));

      if (res.tapIndex === -1) return;

      // 拍照
      if (res.tapIndex === 0) {
        if (isIOS) {
          this._openPicker('camera');
        } else {
          // 显示相机权限说明
          this.$emit('ckeckisShowPer', true);
          this.$emit('ckecknowQer', 'xj');
          const { granted } = await permissionUtils.checkPermission('camera', '需要相机权限以拍照');
          if (granted) {
            this.$emit('ckeckisShowPer', false);
            this._openPicker('camera');
            return;
          }
          this.$emit('ckeckisShowPer', false);
          const confirm = await this.showPermissionDialog('相机权限申请', '我们需要访问您的相机权限，以便您拍照上传');
          if (!confirm) return;
          const result = await permissionUtils.requestPermission('camera', '需要相机权限以拍照');
          if (result) {
            this._openPicker('camera');
          } else {
            locationService.openAppSettings();
          }
        }
      }
      // 从相册选择
      else if (res.tapIndex === 1) {
        if (isIOS) {
          this._openPicker('album');
        } else {
          // 显示存储权限说明
          this.$emit('ckeckisShowPer', true);
          this.$emit('ckecknowQer', 'xc');
          const { granted } = await permissionUtils.checkPermission('photo_library', '需要存储权限以选择照片');
          if (granted) {
            this.$emit('ckeckisShowPer', false);
            this._openPicker('album');
            return;
          }
          this.$emit('ckeckisShowPer', false);
          const confirm = await this.showPermissionDialog('存储权限申请', '我们需要访问您的相册权限，以便您选择照片');
          if (!confirm) return;
          const result = await permissionUtils.requestPermission('photo_library', '需要存储权限以选择照片');
          if (result) {
            this._openPicker('album');
          } else {
            locationService.openAppSettings();
          }
        }
      }
    },

    // 实际打开选择器（图片或视频）
    async _openPicker(sourceType) {
      try {
        if (this.accept === 'image/*') {
          const count = this.maxCount - this.fileList.length;
          if (count <= 0) {
            uni.showToast({ title: `最多上传${this.maxCount}个文件`, icon: 'none' });
            return;
          }
          const res = await uni.chooseImage({
            count: count,
            sizeType: ['compressed'],
            sourceType: [sourceType]
          });
          for (const file of res.tempFiles) {
            await this.uploadFile(file);
          }
        } else if (this.accept === 'video/*') {
          const res = await uni.chooseVideo({
            sourceType: [sourceType],
            compressed: true,
            maxDuration: 60
          });
          await this.uploadFile(res);
        }
      } catch (error) {
        console.error('选择文件失败:', error);
      }
    },
    // 上传文件到OSS
    async uploadFile(file) {
      // 检查文件大小
      if (file.size > this.maxSize * 1024 * 1024) {
        uni.showToast({
          title: `文件大小不能超过${this.maxSize}MB`,
          icon: 'none'
        })
        return Promise.reject(new Error('文件大小超出限制'))
      }
	  let date = new Date().getTime()
	  let imageType;
	  if(this.accept == 'image/*') {
		imageType = file.path.split('.')
	  }else if(this.accept == 'video/*') {
		// #ifdef H5
		imageType = file.name.split('.')
		// #endif
		// #ifdef APP-PLUS || MP-WEIXIN
		imageType = file.tempFilePath.split('.')
		// #endif
	  }
		console.log('imageType',imageType)
	  
	  let artisan = this.type==1 ? 'yh' : this.type==2 ? 'syr' : this.type==3 ? 'sj' : '';
	  let name = `${this.userId}_${artisan}_${date}.${imageType[imageType.length - 1]}`
	  console.log('name',name)
      try {
        // 1. 获取OSS上传凭证
        const ossConfig = await this.getOssConfig()
        // 2. 上传文件
        const uploadRes = await this.uploadToOss(file, ossConfig, name)
        // 3. 添加到文件列表
        const fileUrl = `${ossConfig.host}/${ossConfig.dir}${name}`
		if(this.accept == 'image/*') {
			const newFile = [`${fileUrl}`]
			this.fileList = this.fileList.concat(newFile)
			this.$emit('input', this.fileList)
			this.$emit('change', this.fileList)
			this.$emit('success', newFile)
			return newFile
		}else if(this.accept == 'video/*') {
			const newFile = fileUrl
			this.oneFile = fileUrl
			this.$emit('input', this.oneFile)
			this.$emit('change', this.oneFile)
			this.$emit('success', newFile)
			return newFile
		}
        
      } catch (error) {
        console.error('上传失败:', error)
        this.$emit('error', error)
        throw error
      }
    },
    
    // 获取OSS配置
    async getOssConfig() {
      try {
        const res = await request.post('/user/getalioss',{type: this.type,kind: this.kind})
        return res
      } catch (error) {
        console.error('获取OSS配置失败:', error)
        throw error
      }
    },
    
    // 上传到OSS
    uploadToOss(file, ossConfig, name) {
      return new Promise((resolve, reject) => {
	    // #ifdef H5
        const formData = new FormData()
		formData.append('name',name);
		formData.append('policy', ossConfig.policy);
		formData.append('OSSAccessKeyId', ossConfig.ossAccessKeyId);
		formData.append('success_action_status', '200');
		formData.append('signature', ossConfig.signature);
		formData.append('key', ossConfig.dir + name);
        // file必须为最后一个表单域，除file以外的其他表单域无顺序要求。
        formData.append('file', file);
		fetch(ossConfig.host, { method: 'POST', body: formData},).then((res) => {
		  resolve(res)
		}).catch(()=>{
		  reject(new Error(`上传失败: ${res.statusCode}`))
		})
		// #endif
		
		// #ifdef APP-PLUS || MP-WEIXIN
		let formData = {};
		formData.name = name;
		formData.policy = ossConfig.policy;
		formData.OSSAccessKeyId = ossConfig.ossAccessKeyId;
		formData.success_action_status = '200';
		formData.signature = ossConfig.signature;
		formData.key = ossConfig.dir + name;
		formData.file = file;
		let path;
		if(this.accept == 'image/*') {
			path = file.path
		}else if(this.accept == 'video/*') {
			// #ifdef H5
			path = file.name
			// #endif
			// #ifdef APP-PLUS || MP-WEIXIN
			path = file.tempFilePath
			// #endif
		}
		// 使用 uni.uploadFile 上传文件（支持多平台）
		uni.uploadFile({
		  url: ossConfig.host,
		  filePath: path, // 手机端文件路径
		  name: 'file',
		  formData: {
		    key: ossConfig.dir + name, // 文件名
		    policy: ossConfig.policy, // 后台获取超时时间
		    OSSAccessKeyId: ossConfig.ossAccessKeyId, // 后台获取临时ID
		    success_action_status: 200, // 让服务端返回200,不然，默认会返回204
		    signature: ossConfig.signature // 后台获取签名
		  },
		  success(res) {
			resolve(`${ossConfig.host}/${ossConfig.dir}${name}`)
		  }
		});
		// #endif
      })
	
    },
    
    // 预览图片
    handlePreview(index) {
      uni.previewImage({
        current: index,
        urls: this.fileList.map(item => item.url)
      })
    },
    
    // 删除文件
    handleDelete(index) {
      // uni.showModal({
      //   title: '提示',
      //   content: '确定删除该文件吗？',
      //   success: (res) => {
      //     if (res.confirm) {
			if(this.accept == 'image/*') {
				const deletedFile = this.fileList[index]
				this.fileList.splice(index, 1)
				this.$emit('input', this.fileList)
				this.$emit('change', this.fileList)
				this.$emit('delete', deletedFile, index)
			}else if(this.accept == 'video/*') {
				const deletedFile = this.oneFile
				this.oneFile = ''
				this.$emit('input', this.oneFile)
				this.$emit('change', this.oneFile)
				this.$emit('delete', deletedFile)
			}
            
      //     }
      //   }
      // })
    }
  }
}
</script>

<style scoped>
/* .ali-oss-uploader {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  justify-items: center;
  align-items: center;
  margin-top: 20rpx;
  position: relative;
} */

.preview-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  justify-items: center;
  align-items: center;
  position: relative;
}
.upload-btn {
  width: 200rpx;
  height: 200rpx;
  border: 2rpx dashed #ddd;
  border-radius: 8rpx;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
  /* margin-top: 20rpx; */
}

.plus-icon {
  font-size: 60rpx;
  color: #999;
  line-height: 1;
}

.btn-text {
  font-size: 24rpx;
  color: #666;
  margin-top: 10rpx;
}

.tips-text {
  font-size: 24rpx;
  color: #999;
  margin-top: 10rpx;
}

.preview-item {
  position: relative;
  width: 200rpx;
  height: 200rpx;
  margin-top: 20rpx;
}

.preview-image {
  width: 200rpx;
  height: 200rpx;
  border-radius: 8rpx;
}

.delete-icon {
  position: absolute;
  top: -10rpx;
  right: -10rpx;
  width: 40rpx;
  height: 40rpx;
  background-color: #ff4d4f;
  color: white;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 32rpx;
  z-index: 1;
}
</style>