<template>
	<view class="container">
		<view class="example">
			<uni-forms ref="dynamicForm" :model="form" label-width="80px">
				<uni-forms-item label="巡检点" name="inspectionPoint">
					<uni-easyinput disabled :value="form.inspectionPoint" placeholder="请输入巡检点"></uni-easyinput>
				</uni-forms-item>
				<uni-forms-item label="巡检要求" name="inspectionRequirements">
					<uni-easyinput type="textarea" disabled :value="form.inspectionRequirements"
						placeholder="请输入巡检要求"></uni-easyinput>
				</uni-forms-item>
				<uni-forms-item label="图片上传">
					<view class="example-body">
						<uni-file-picker limit="3" :sourceType="sourceType" :value="img" title="最多选择3张图片"
							file-mediatype="image" @delete="deleteImg" @select="upload"
							:auto-upload="false"></uni-file-picker>
					</view>
				</uni-forms-item>
				<!-- 备注 -->
				<uni-forms-item label="备注1" name="remark">
					<uni-easyinput type="textarea" v-model="form.remark" placeholder="请输入备注"></uni-easyinput>
				</uni-forms-item>
			</uni-forms>
			<view class="button-group">
				<button class="btn btn-primary" @click="submit()">提交</button>
				<button class="btn btn-cancel" @click="cancel()">取消</button>
			</view>
		</view>
		<!-- 消息提示框 -->
		<view>
			<uni-popup ref="alertDialog" type="dialog">
				<uni-popup-dialog :type="msgType" title="消息" :content="messageText" @confirm="dialogConfirm"
					showClose="false"></uni-popup-dialog>
			</uni-popup>
		</view>

	</view>
</template>

<script>
	import { addRecord } from "@/api/inspection/record.js"
	import { addWatermarkToImage } from "@/utils/watermark.js"
	import appConfig from "@/config"
	import { getToken } from "@/utils/auth"
	
	// ------- URL 安全拼接，避免出现 /undefined/common/upload -------
	function joinURL(base, path) {
	  const b = (base || "").replace(/\/+$/, "")
	  const p = (path || "").replace(/^\/+/, "")
	  return `${b}/${p}`
	}
	const BASE_URL = appConfig?.baseUrl || (process.env.VUE_APP_BASE_API || "")
	const UPLOAD_URL = joinURL(BASE_URL, "/common/upload")
	
	export default {
	  data() {
	    return {
	      form: {
	        inspectionType: 0,
	        inspectorId: this.$store.state.user.nickName,
	        inspectionPoint: "",
	        inspectionRequirements: "",
	        inspectionImg: "",
	        ImgUrl: [], // 后端返回的文件名/URL
	        remark: ""
	      },
	      img: [], // uni-file-picker 预览
	      sourceType: ["camera"],
	      msgType: "",
	      messageText: "",
	      isUploading: false,
	      isMobileBrowser: false
	    }
	  },
	  methods: {
	    async submit() {
	      if (this.isUploading) {
	        this.showMessage("warning", "图片正在上传中，请稍等")
	        return
	      }
	      if (!Array.isArray(this.form.ImgUrl) || this.form.ImgUrl.length === 0) {
	        this.showMessage("error", "请选择要上传的图片")
	        return
	      }
	      this.form.inspectionImg = this.joinList()
	      try {
	        const res = await addRecord(this.form)
	        if (res.code === 200) {
	          this.showMessage("success", "打卡成功")
	        } else {
	          this.showMessage("error", res.msg || "打卡失败")
	        }
	      } catch (err) {
	        this.showMessage("error", `提交失败: ${err.message}`)
	      }
	    },
	
	    // 删除预览 & 同步删除结果
	    deleteImg(e) {
	      const url = e?.tempFile?.url || e?.tempFile?.path
	      const idx = this.img.findIndex((x) => x.url === url)
	      if (idx !== -1) {
	        // 释放预览 URL 内存
	        try {
	          const toRevoke = this.img[idx]?.url
	          toRevoke && toRevoke.startsWith("blob:") && URL.revokeObjectURL(toRevoke)
	        } catch {}
	        this.img.splice(idx, 1)
	        this.form.ImgUrl.splice(idx, 1)
	      }
	    },
	
	    // 选择文件（支持多张）
    async upload(e) {
      if (!e?.tempFiles?.length) return
      if (this.isUploading) {
        this.showMessage("warning", "图片正在上传中，请稍等")
        return
      }

      this.isUploading = true
      try {
        for (const tf of e.tempFiles) {
          await this.handleImageUpload(tf)
        }
      } catch (err) {
        console.error(err)
        const msg = err?.errMsg || err?.message || (typeof err === "string" ? err : JSON.stringify(err))
        this.showMessage("error", `图片上传失败：${msg}`)
      } finally {
        this.isUploading = false
      }
    },
	
	    // 单张：加水印 -> 压缩(H5) -> 预览 -> 上传
	    async handleImageUpload(tempFile) {
	      // H5：uni-file-picker 的 e.tempFiles[i].file 就是 File
	      const rawFile =
	        tempFile?.file instanceof File
	          ? tempFile.file
	          : tempFile instanceof File
	          ? tempFile
	          : null
	      if (!rawFile) {
	        throw new Error("未获取到有效的 File 对象（仅支持 H5）")
	      }
	
	      const watermarkText = `${this.form.inspectionPoint || "未命名地点"} \n${this.getCurrentDate()}`
	
	      // 水印（返回 Blob 或 File）
	      let watermarked = await addWatermarkToImage(rawFile, watermarkText)
	      if (!(watermarked instanceof File)) {
	        // 统一转回 File
	        watermarked = this.blobToFile(
	          watermarked,
	          rawFile.name || `image_${Date.now()}.jpg`
	        )
	      }
	
	      // 压缩（仅 H5）
	      const finalFile = await this.compressImageForMobile(watermarked, {
	        quality: 0.6,
	        maxWidth: 1200,
	        maxHeight: 1200,
	        mime: "image/jpeg"
	      })
	
	      // 预览（本地 blob URL）
	      const previewUrl = URL.createObjectURL(finalFile)
	      this.img.push({
	        url: previewUrl,
	        name: finalFile.name || `image_${Date.now()}.jpg`,
	        extname: "jpg"
	      })
	
	      // 上传（H5 用 file 字段）
	      const uploadedName = await this.uploadFileWithUni(finalFile)
	      this.form.ImgUrl.push(uploadedName)
	
	      // 可选：延时释放预览 URL，避免立即失效
	      setTimeout(() => {
	        try {
	          URL.revokeObjectURL(previewUrl)
	        } catch {}
	      }, 30000)
	    },
	
	    // —— 仅 H5：File 压缩（canvas 尺寸+质量）——
	    async compressImageForMobile(file, opts = {}) {
	      const { quality = 0.6, maxWidth = 1200, maxHeight = 1200, mime = "image/jpeg" } = opts
	      if (!(file instanceof File)) return file
	
	      const dataURL = await new Promise((resolve, reject) => {
	        const reader = new FileReader()
	        reader.onload = () => resolve(reader.result)
	        reader.onerror = () => reject(new Error("文件读取失败"))
	        reader.readAsDataURL(file)
	      })
	
	      const img = await new Promise((resolve, reject) => {
	        const image = new Image()
	        image.onload = () => resolve(image)
	        image.onerror = () => reject(new Error("图片加载失败"))
	        image.src = dataURL
	      })
	
	      const { w, h } = this.calcTargetSize(img.width, img.height, maxWidth, maxHeight)
	      const canvas = document.createElement("canvas")
	      canvas.width = w
	      canvas.height = h
	      const ctx = canvas.getContext("2d")
	      ctx.imageSmoothingQuality = "high"
	      ctx.drawImage(img, 0, 0, w, h)
	
	      const blob = await this.canvasToBlob(canvas, mime, quality)
	      if (!blob) return file
	      if (blob.size >= file.size) return file // 压缩后更大就不压了
	      return this.blobToFile(blob, file.name)
	    },
	
	    // 计算目标尺寸
	    calcTargetSize(imgW, imgH, maxW, maxH) {
	      let w = imgW,
	        h = imgH
	      if (w > maxW || h > maxH) {
	        const ratio = Math.min(maxW / w, maxH / h)
	        w = Math.round(w * ratio)
	        h = Math.round(h * ratio)
	      }
	      return { w, h }
	    },
	
	    // toBlob 兼容
	    canvasToBlob(canvas, type, quality) {
	      return new Promise((resolve) => {
	        if (canvas.toBlob) {
	          canvas.toBlob((blob) => resolve(blob), type, quality)
	        } else {
	          const dataURL = canvas.toDataURL(type, quality)
	          const arr = dataURL.split(",")
	          const mime = arr[0].match(/:(.*?);/)[1]
	          const bstr = atob(arr[1])
	          let n = bstr.length
	          const u8arr = new Uint8Array(n)
	          while (n--) u8arr[n] = bstr.charCodeAt(n)
	          resolve(new Blob([u8arr], { type: mime }))
	        }
	      })
	    },
	
	    // Blob -> File
	    blobToFile(blob, filename) {
	      return new File([blob], filename || `img_${Date.now()}.jpg`, {
	        type: blob.type || "image/jpeg"
	      })
	    },
	
	    // H5: 用 uni.uploadFile 直接传二进制 File
	    uploadFileWithUni(file) {
	      return new Promise((resolve, reject) => {
	        uni.uploadFile({
	          url: UPLOAD_URL,
	          name: "file",
	          file, // H5 传 File；不要传 filePath
	          header: { Authorization: "Bearer " + getToken() },
	          success: (res) => {
	            try {
	              if (res.statusCode && res.statusCode !== 200) {
	                throw new Error(`HTTP ${res.statusCode}`)
	              }
	              const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data
	              if (data && data.code === 200) {
	                resolve(data.fileName || data.url)
	              } else {
	                reject(new Error((data && data.msg) || "上传失败"))
	              }
	            } catch (e) {
	              reject(new Error("上传响应解析失败"))
	            }
	          },
	          fail: async (err) => {
	            const msg = err?.errMsg || "uploadFile fail"
	            if (msg.includes("file error") || msg.includes("fail")) {
	              try {
	                const form = new FormData()
	                form.append("file", file)
	                const resp = await fetch(UPLOAD_URL, {
	                  method: "POST",
	                  headers: { Authorization: "Bearer " + getToken() },
	                  body: form
	                })
	                if (!resp.ok) return reject(new Error(`HTTP ${resp.status}`))
	                const data = await resp.json()
	                if (data && data.code === 200) {
	                  return resolve(data.fileName || data.url)
	                }
	                return reject(new Error((data && data.msg) || "上传失败"))
	              } catch (e) {
	                return reject(new Error(e?.message || msg))
	              }
	            }
	            reject(new Error(msg))
	          }
	        })
	      })
	    },
	
	    cancel() {
	      uni.reLaunch({ url: "/pages/work/index" })
	    },
	
	    joinList() {
	      return this.form.ImgUrl.join(",")
	    },
	
	    getCurrentDate() {
	      const now = new Date()
	      const y = now.getFullYear()
	      const m = String(now.getMonth() + 1).padStart(2, "0")
	      const d = String(now.getDate()).padStart(2, "0")
	      const hh = String(now.getHours()).padStart(2, "0")
	      const mm = String(now.getMinutes()).padStart(2, "0")
	      const ss = String(now.getSeconds()).padStart(2, "0")
	      return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
	    },
	
	    dialogConfirm() {
	      if (this.msgType === "success") {
	        uni.reLaunch({ url: "/pages/work/inspection/recordList/index" })
	      }
	    },
	
	    showMessage(type, text) {
	      this.msgType = type
	      this.messageText = text
	      this.$refs.alertDialog.open()
	    },
	
	    checkMobileBrowser() {
	      const ua = navigator.userAgent.toLowerCase()
	      const isMobile = /iphone|ipod|android|windows phone|mobile|blackberry/.test(ua)
	      this.isMobileBrowser = isMobile || window.__uniAppWebview
	    }
	  },
	  onLoad(option) {
	    this.form.inspectionPoint = option.inspectionPoint || ""
	    this.form.inspectionRequirements = option.inspectionRequirements || ""
	    this.form.inspectionPointId = option.inspectionPointId || ""
	  },
	  mounted() {
	    if (!BASE_URL) {
	      console.warn("[上传] baseUrl 未配置，当前上传地址可能异常：", UPLOAD_URL)
	    }
	    this.checkMobileBrowser()
	  }
	}
</script>



<style lang="scss">
	page {
		display: flex;
		flex-direction: column;
		box-sizing: border-box;
		background-color: #fff;
		height: 90vh;
		/* 使页面高度占满整个视口 */
	}

	.container {
		flex: 1;
		/* 让 container 占满剩余空间 */
		display: flex;
		flex-direction: column;
		/* 设置为列方向 */
	}

	.example {
		flex: 1;
		/* 让 example 占满 container 的剩余空间 */
		display: flex;
		flex-direction: column;
		/* 设置为列方向，确保子元素垂直排列 */
		padding: 15px;
		background-color: #fff;
	}

	// 样式沉底
	.button-group {
		position: fixed;
		bottom: 20px;
		left: 0;
		/* 使用 margin-top: auto 来将按钮组推到 example 容器的底部 */
		display: flex;
		width: 100%;
		justify-content: space-around;
	}

	.button-group button {
		flex: 1;
		background: #fff;
		color: #000;
		/* 使按钮平分可用空间 */
		/* 可能还需要设置一些其他的样式来确保按钮看起来正确，比如 text-align, padding 等 */
	}
</style>