<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> -->
			<image src="/static/images/evaluate/upload.png" class="upload-btn"  :style="btnStyle" @click="handleUpload" v-if="fileList.length < maxCount"></image>
		</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() {
	  // 判断
      try {
		const systemInfo = uni.getSystemInfoSync()
		if(systemInfo.platform === 'ios') {
			this.openCamera();
		}else {
			let xcpermission = '';
			let xjpermission = '';
			if(systemInfo.platform === 'ios') {
				xcpermission = 'photo_library',
				xjpermission = 'camera'
			}else {
				xcpermission = `android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE`
				xjpermission = 'android.permission.CAMERA'
			}
			const xjfirstRequest = !plus.storage.getItem(`perm_${xjpermission}`)
			const xcfirstRequest = !plus.storage.getItem(`perm_${xcpermission}`)
			if(xcfirstRequest || xjfirstRequest) {
				// this.isShowPer = true;
				console.log('ckeckisShowPer',true)
				this.$emit('ckeckisShowPer',true)
			}
			
			// 1. 检查权限
			 // const { granted } = await permissionUtils.checkPermission('photo_library', '需要相册权限用于上传照片');
			this.$emit('ckecknowQer','xc')
			const xc = await permissionUtils.checkPermission('photo_library', '需要相册权限用于上传照片');
			this.$emit('ckecknowQer','xj')
			const xj = await permissionUtils.checkPermission('camera', '需要相机权限用于拍摄照片');
			this.$emit('ckeckisShowPer',false)
			this.$emit('ckecknowQer','')
			if (xc.granted && xj.granted) {
			  this.openCamera();
			  return;
			}
			// this.isShowPer = false;
			// 2. 显示权限说明弹窗
			const confirm = await this.showPermissionDialog(
			  '相机相册权限申请',
			  '我们需要访问您的相机以及相册以完成更换头像功能'
			);
			
			if (!confirm) return;
			
			// 3. 请求权限
			this.$emit('ckeckisShowPer',true)
			this.$emit('ckecknowQer','xc')
			const result1 = await permissionUtils.requestPermission('photo_library', '我们需要访问您的相册以上传图片/视频');
			this.$emit('ckecknowQer','xj')
			const result2 = await permissionUtils.requestPermission('camera', '我们需要访问您的相机以上传图片/视频');
			if (result1 && result2) {
			  this.openCamera();
			} else {
			  locationService.openAppSettings();
			  // uni.showToast({ title: '相机权限被拒绝', icon: 'none' });
			}
			this.$emit('ckeckisShowPer',false)
			this.$emit('ckecknowQer','')
		}
        
      } catch (error) {
        console.error('上传出错:', error)
        this.$emit('error', error)
      } finally {
        this.loading = false
      }
    },
    async openCamera() {
		if (this.loading) return
		if (this.fileList.length >= this.maxCount) {
		  return uni.showToast({
		    title: `最多上传${this.maxCount}个文件`,
		    icon: 'none'
		  })
		}
		
		try {
			this.loading = true
			let res;
			let tempFiles;
			if(this.accept == 'image/*') {
				const res = await uni.chooseImage({
				  count: this.maxCount - this.fileList.length,
				  sizeType: ['original', 'compressed'],
				  sourceType: ['album', 'camera']
				})
				const tempFiles = res.tempFiles
				for (const file of tempFiles) {
				  await this.uploadFile(file)
				}
			}else if(this.accept == 'video/*') {
				const res = await uni.chooseVideo({
				  count: 1,
				  sourceType: ['album', 'camera'],
				  compressed: false
				})
				// #ifdef H5
				const file = res.tempFile;
				// #endif
				// #ifdef APP-PLUS || MP-WEIXIN
				const file = res;
				// #endif
				await this.uploadFile(file)
			}
		} catch (error) {
			console.error('上传出错:', error)
			this.$emit('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(4, 1fr);
  justify-items: center;
  align-items: center;
  position: relative;
}
.upload-btn {
  width: 148rpx;
  height: 148rpx;
  /* 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: 148rpx;
  height: 148rpx;
  margin-top: 20rpx;
}

.preview-image {
  width: 148rpx;
  height: 148rpx;
  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>