<template>
	<view>
		<cpn-navbar title="质控回访" :is-back="true"></cpn-navbar>

		<view class="container">
			<u-form :model="form" ref="uForm" :label-width="200" :error-type="['message', 'border-bottom']">
				<u-form-item label="日期" prop="date" label-position="left">
					<u-input v-model="form.date" disabled type="text"></u-input>
				</u-form-item>
				<u-form-item label="客户" prop="customer_name" label-position="left">
					<u-input v-model="form.customer_name" disabled type="text"></u-input>
				</u-form-item>
				<!-- 联系方式 -->
				<u-form-item label="联系方式" label-position="left">
					<u-input v-model="editCustomer.phone" type="text" placeholder="请输入联系方式"></u-input>
				</u-form-item>
				<!-- 状态 单选组 0正常 1死亡 -->
				<u-form-item label="状态" label-position="left">
					<u-radio-group v-model="editCustomer.is_dead" active-color="#1479FF">
						<u-radio :name="0">正常</u-radio>
						<u-radio :name="1" style="margin-left: 24rpx;">死亡</u-radio>
					</u-radio-group>
				</u-form-item>
				<!-- 默认地址 显示 default=1 的一条，仅显示 address；提供获取位置按钮更新/新增 -->
				<u-form-item label="默认地址" label-position="left">
					<view>
						<view v-if="defaultCustomerAddress">
							<view style="word-break: break-all;">{{ defaultCustomerAddress.address || '' }}</view>
							<view style="margin-top: 12rpx; display: flex; align-items: center;">
								<u-button size="mini" type="primary" @click="updateDefaultCustomerAddress">获取位置</u-button>
							</view>
						</view>
						<view v-else>
							<view style="display: flex; align-items: center;">
								<u-button size="mini" type="primary" @click="createDefaultCustomerAddress">获取位置</u-button>
							</view>
						</view>
					</view>
				</u-form-item>

				<view style="display: flex; align-items: center;margin-top: 20rpx;justify-content: center;">
					<u-button size="medium" type="primary" style="margin-left: 12rpx;" @click="saveCustomerInfo">更新用户信息</u-button>
				</view>

				<u-form-item label="护理员" prop="nurse_name" label-position="left">
					<u-input v-model="form.nurse_name" type="text"  placeholder="请输入护理员"></u-input>
				</u-form-item>
				<u-form-item :required="item.type==='checkbox'?false:true" v-for="(item,index) in form.forms" :key="index" :label="item.ask" :prop="index" label-position="top">
					<u-checkbox-group v-if="item.type==='checkbox'" ref="serve" @change="e => checkboxChange(e)">
						<u-checkbox v-for="(item1, index1) in item.options" :key="index1" :name="item1.name"
							v-model="item1.checked">
							{{ item1.name }}
						</u-checkbox>
					</u-checkbox-group>
					<u-input v-else @blur="blurInput(item)" v-model="item.score" type="number" placeholder="请输入分值"></u-input>
				</u-form-item>
				<u-form-item label="总分(得90分及以上为及格)" prop="total_score" label-position="top">
					<u-input v-model="form.total_score" disabled type="text"></u-input>
				</u-form-item>
				<u-form-item label="对护理员哪些方面要求改进" prop="tip" label-position="top">
					<u-input v-model="form.tip" type="textarea"></u-input>
				</u-form-item>
				<u-form-item label="对护理员有哪些方面肯定" prop="sure" label-position="top">
					<u-input v-model="form.sure" type="textarea"></u-input>
				</u-form-item>
				<u-form-item label="备注" prop="remark" label-position="top">
					<u-input v-model="form.remark" type="textarea"></u-input>
				</u-form-item>
				<u-form-item label="回访图片">
					<u-upload ref="uUpload" :custom-btn="true" :action="action" :file-list="fileList"
						:source-type="['camera']">
						<view slot="addBtn" class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
							<u-icon name="camera" size="60" color="#c0c4cc" label="点击拍摄" label-pos="bottom"></u-icon>
						</view>
					</u-upload>
				</u-form-item>
				<u-form-item label="服务对象/家属签名" required prop="sign_image_id">
					<view>
						<u-button type="primary" size="mini" :throttle-time="3000"
							@click="pageTo('/pages/sign/sign?key=vuex_sign_image')">点击签名</u-button>
						<image v-if="vuex_sign_image || (detail.sign_image && detail.sign_image.url)"
							:src="vuex_sign_image || (detail.sign_image && detail.sign_image.url)"
							style="width: 260rpx;object-fit: cover;transform: rotate(270deg);"
							@click="showimg(vuex_sign_image || (detail.sign_image && detail.sign_image.url))"></image>
					</view>
				</u-form-item>
				<u-form-item label="调查人员签名" required prop="admin_sign_image_id">
					<view>
						<u-button type="primary" size="mini" :throttle-time="3000"
							@click="pageTo('/pages/sign/sign?key=vuex_admin_sign_image')">点击签名</u-button>
						<image v-if="vuex_admin_sign_image || (detail.admin_sign_image && detail.admin_sign_image.url)"
							:src="vuex_admin_sign_image || (detail.admin_sign_image && detail.admin_sign_image.url)"
							style="width: 260rpx;object-fit: cover;transform: rotate(270deg);"
							@click="showimg(vuex_admin_sign_image || (detail.admin_sign_image && detail.admin_sign_image.url))">
						</image>
					</view>
				</u-form-item>
				<u-form-item label="所在位置">
					<view>
						<u-button type="primary" size="mini" :throttle-time="3000" @click="getLoaction">获取位置</u-button>
						<view style="word-break: break-all;">
							{{ `${(form.longitude || form.latitude) ? ('(' + form.longitude + ',' + form.latitude + ')') : ''}${form.address}` }}
						</view>
					</view>
				</u-form-item>
			</u-form>
			<u-button type="primary" @click="submit">提交</u-button>
		</view>
	</view>
</template>

<script>
	import QQMapWX from '@/libs/qqmap-wx-jssdk.js'
	import {
		ROOTPATH
	} from "@/common/config"
	import moment from "@/libs/moment.min";
	export default {
		data() {
			return {
				action: `${ROOTPATH}/api/admin/upload-file`,
				fileList: [],
				id: "",
				type: "add",
				detail: {},
				customerInfo: {},
				editCustomer: {
					phone: '',
					is_dead: 0,
					customer_address: []
				},
				form: {
					customer_id: "",
					customer_name:'',
					date: '',
					nurse_name: '',
					forms: [{
						ask: '执证上岗（工作证完整无损且佩戴在身）(2分)',
						max: 2,
						min: 0,
						score: ''
					}, {
						ask: '工作服整洁、穿戴整齐(3分)',
						max: 3,
						min: 0,
						score: ''
					}, {
						ask: '仪容仪表（指甲、束发）(2分)',
						max: 2,
						min: 0,
						score: ''
					}, {
						ask: '对应本次服务所需工具齐全、性能完好(3分)',
						max: 3,
						min: 0,
						score: ''
					}, {
						ask: '上门核对客户信息正确；地址、电话正确(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '告知客户可以提供的服务项目及本次上门服务的时长(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '客户选择本次服务项目（合法合规）(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '服务态度积极主动，不推托，不生硬拒绝（微笑服务）(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '服务内容、纸质工单、系统派单三者一致（个性化服务最后）(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '工单服务项目能保质保量完成（质量标准参考入户检查表）(30分)',
						max: 30,
						min: 0,
						score: ''
					}, {
						ask: '抽查背诵一项服务流程(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '评估现场服务流程准确(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '能准确知晓并说出公司全称（每次上门先介绍）(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '每次上门服务前都提前预约（至少提前一天预约）(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '服务前后对比明显，所需部位消毒及时准确(5分)',
						max: 5,
						min: 0,
						score: ''
					}, {
						ask: '所需服务技能娴熟（欠缺一项扣2分，扣完为止）(10分)',
						max: 10,
						min: 0,
						score: ''
					}, {
						ask: '其他（涉及此类一律按照 0 分处理）',
						max: 10,
						type: 'checkbox',
						min: 0,
						score: '',
						options: [{
							name: '服务中存在人身及环境安全',
							checked: false,
						}, {
							name: '服务中脱岗',
							checked: false,
						}, {
							name: '无正当理由不提供服务',
							checked: false,
						}, {
							name: '恶意消耗工时、虚假工单、重叠工单、人卡不符、多卡一户现象',
							checked: false,
						}, {
							name: '拒绝客户提出的正当要求',
							checked: false,
						}, {
							name: '替代客户签名',
							checked: false,
						}, {
							name: '存在向客户推销非官方商品、索要物品或货币行为',
							checked: false,
						}, {
							name: '不积极配合公司稽查',
							checked: false,
						}, {
							name: '违反公司原则性规章制度行为',
							checked: false,
						}]
					}],

					total_score: '',
					tip: '',
					sure: "",
					remark: '',
					file_ids: [],
					sign_image_id: "",
					admin_sign_image_id: "",
					latitude: "",
					longitude: "",
					address: "",

				},
				rules: {
					// nurse_name: [
					//   {
					//     required: true,
					//     type: 'string',
					//     message: '请填写护理员姓名',
					//     trigger: ['change','blur']
					//   }
					// ],
					sign_image_id: [{
						validator: (rule, value, callback) => {
							if (this.vuex_sign_image || value) {
								callback()
							} else {
								callback(new Error('请签名'))
							}
						}
					}],
					admin_sign_image_id: [{
						validator: (rule, value, callback) => {
							if (this.vuex_admin_sign_image || value) {
								callback()
							} else {
								callback(new Error('请签名'))
							}
						}
					}]
				},
			};
		},
		watch: {
			// 深度监听 forms 数组的变化（包括元素新增、删除、属性修改）
			'form.forms': {
				handler() {
					this.calculateTotalScore();
				},
				deep: true, // 深度监听
				immediate: true // 初始化时立即执行一次
			}
		},
		onLoad(option) {
			this.form.customer_id = option.customer_id;
			this.id = option.id;
			this.type = option.id ? 'edit' : 'add';
			if (this.type === 'edit') {
				this.getDetail()
			}else{
				this.form.date = moment().format('YYYY-MM-DD')
				this.form.customer_name = option.customer_name?option.customer_name:''
			}
			if (this.form.customer_id) {
				this.getCustomerInfo()
			}
		},
		onReady() {
			this.load();
			this.$refs.uForm.setRules(this.rules);
		},
		computed: {
			defaultCustomerAddress(){
				const idx = this.editCustomer.customer_address.findIndex(i => Number(i.default) === 1)
				return idx > -1 ? this.editCustomer.customer_address[idx] : null
			}
		},
		methods: {
			async getCustomerInfo(){
				try{
					const res = await this.$u.api.adminCustomerInfo({ id: this.form.customer_id })
					this.customerInfo = res
					// 初始化可编辑数据
					this.editCustomer.phone = res.phone || ''
					this.editCustomer.is_dead = Number(res.is_dead || 0)
					this.editCustomer.customer_address = Array.isArray(res.customer_address) ? JSON.parse(JSON.stringify(res.customer_address)) : []
				}catch(e){
					console.error('adminCustomerInfo error', e)
				}
			},
			defaultAddrIndex() {
				return this.editCustomer.customer_address.findIndex(i => Number(i.default) === 1)
			},
			// 获取定位并更新默认地址（已有默认地址）
			async updateDefaultCustomerAddress(){
				try{
					const res = await uni.getLocation({ type: 'gcj02', isHighAccuracy: true })
					const location = Array.isArray(res) ? res[1] : res
					if(!location) throw new Error('定位失败')
					await new Promise((resolve, reject) => {
						this.qqmapsdk.reverseGeocoder({
							location: { latitude: location.latitude, longitude: location.longitude },
							success: (r) => resolve(r),
							fail: (err) => reject(err)
						})
					}).then(geo => {
						const idx = this.defaultAddrIndex()
						const addr = geo.result.address + (geo.result.formatted_addresses?.recommend || '')
						// 如果已存在默认地址，先移除该条（避免携带旧的 id）
						if (idx > -1) {
							this.editCustomer.customer_address.splice(idx, 1)
						}
						// 插入新的默认地址，且不包含 id 字段
						this.editCustomer.customer_address.push({ address: addr, lat: location.latitude, lng: location.longitude, default: 1 })
						uni.showToast({ icon: 'none', title: '位置已更新' })
					})
				}catch(e){
					uni.showToast({ icon: 'none', title: '定位失败' })
				}
			},
			// 无默认地址时创建
			async createDefaultCustomerAddress(){
				await this.updateDefaultCustomerAddress()
			},
			saveCustomerInfo(){
				const payload = {
					...this.customerInfo,
					id: this.form.customer_id,
					is_dead: this.editCustomer.is_dead,
					phone: this.editCustomer.phone,
					customer_address_list: this.editCustomer.customer_address
				}
				this.$u.api.adminCustomerSave(payload).then(()=>{
					uni.showToast({ icon:'success', title:'已更新' })
					this.getCustomerInfo()
				})
			},
			
			showimg(url) {
				if (url)
					this.$showimg({
						imgs: [url],
						current: 0
					})
			},
			pageTo(url) {
				uni.navigateTo({
					url
				})
			},
			load() {
				this.qqmapsdk = new QQMapWX({
					key: 'I5FBZ-LMN33-BK63F-OGUO7-XE3JK-WJBP5'
				});
			},
			getLoaction() {
				return new Promise((resolve, reject) => {
					uni.getLocation({
						type: 'gcj02',
						isHighAccuracy: true
					}).then(res => {
						if (res[1]) {
							this.form.latitude = res[1]?.latitude
							this.form.longitude = res[1]?.longitude

							this.qqmapsdk.reverseGeocoder({
								location: {
									latitude: this.form.latitude,
									longitude: this.form.longitude
								},
								success: (res) => {
									this.form.address = res.result.address + res.result
										.formatted_addresses.recommend
									console.log(this.form)
									resolve(res)
								},
								fail: (err) => {
									reject(err)
								}
							})
						} else {
							uni.showToast({
								icon: 'none',
								title: '操作频繁,请稍后再试'
							})
							reject(res)
							console.log(res);
						}
					})
				})
			},
			checkboxChange(e, item) {
				let arr = e.filter(i => i?.trim())
				console.log("arr", e, arr)
				// this.$set(item, 'score', arr)
			},
			blurInput(item){
				console.log("blur",item)
				if(!this.validateNumberRange(item.score,item.min,item.max)){
					uni.showToast({
						title: "请输入正确的分值",
						icon: "none"
					})
					item.score = 0
				}
			},
			// 计算总分
			calculateTotalScore(form) {
				// 处理 forms 不存在或非数组的情况
				if (!Array.isArray(this.form.forms)) {
					this.form.total_score = 0;
					return;
				}
				// 检查是否存在任何一个选项的 checked 为 true
				const hasCheckedOption = this.form.forms.some(item => {
					// 如果 item.options 存在且包含 checked 为 true 的项
					return Array.isArray(item.options) &&
						item.options.some(option => option.checked === true);
				});
			
				// 如果存在 checked 为 true 的选项，直接返回 0 分
				if (hasCheckedOption) {
					this.form.total_score = 0;
					this.form.forms.map(item=>item.score=0)
					return;
				}
				// 否则，正常累加所有项的分数
				const total = this.form.forms.reduce((sum, item) => {
					// 将 item.score 转换为数字，非数字默认 0
					const score = Number(item.score) || 0;
					return sum + score;
				}, 0);
			
				this.form.total_score = total;
			},
			// 判断是否为有效数子
			validateNumberRange(value, min, max) {
			  // 步骤1：判断值是否为有效数字（处理字符串形式的数字）
			  let num;
			  
			  // 如果已经是数字类型，直接使用
			  if (typeof value === 'number') {
			    num = value;
			  } 
			  // 如果是字符串，尝试转换为数字
			  else if (typeof value === 'string') {
			    // 去除首尾空格
			    const trimmed = value.trim();
			    
			    // 使用 parseFloat 转换，并验证是否完全匹配数字格式
			    num = parseFloat(trimmed);
			    
			    // 如果转换后不是NaN，且字符串完全等于转换后的数字字符串（确保没有多余字符）
			    if (isNaN(num) || trimmed !== String(num)) {
			      return false;
			    }
			  } 
			  // 其他类型（如 null、object 等）直接判定为无效
			  else {
			    return false;
			  }
			  
			  // 步骤2：检查数字是否在范围内（包含边界）
			  return num >= min && num <= max;
			},
			/**
			 * 验证表单数据
			 * @param {Array} forms - 表单数据数组
			 * @returns {Object} - 验证结果 { isValid: Boolean, errorMsg: String }
			 */
			validateForm(forms) {
			  // 1. 检查是否存在特殊项（包含 options 且有 checked=true）
			  const specialItem = forms.find(item => 
			    Array.isArray(item.options) && 
			    item.options.some(option => option.checked === true)
			  );
			
			  // 如果存在特殊项被勾选，直接返回总分0
			  if (specialItem) {
				forms.map(item=>item.score = 0)
			    return { isValid: true, totalScore: 0, errorMsg: '' };
			  }
			
			  // 2. 验证其他项的分数是否有效（在 min 和 max 之间）
			  for (const item of forms) {
			    // 跳过特殊项
			    if (Array.isArray(item.options)) continue;
			
			    const { score, min, max } = item;
			    const parsedScore = parseFloat(score);
			
			    // 检查分数是否为有效数字
			    if (isNaN(parsedScore) || !isFinite(parsedScore)) {
			      return { isValid: false, totalScore: 0, errorMsg: `请输入有效的分数：${item.ask}` };
			    }
			
			    // 检查分数是否在范围内
			    if (parsedScore < min || parsedScore > max) {
			      return { isValid: false, totalScore: 0, errorMsg: `分数超出范围：${item.ask} (${min}-${max}分)` };
			    }
			  }
			  // 3. 计算总分（当所有项都有效时）
			  const totalScore = forms.reduce((sum, item) => {
			    // 跳过特殊项（已处理）
			    if (Array.isArray(item.options)) return sum;
			    
			    // 累加有效分数
			    return sum + parseFloat(item.score);
			  }, 0);
			
			  return { isValid: true, totalScore, errorMsg: '' };
			},
			submit() {
				console.log("this.form", this.form)
				const res = this.validateForm(this.form.forms)
				if(!res.isValid){
					uni.showToast({
						title:res.errorMsg,
						icon:'none',
					})
					return
				}
				const uploadSignImage = () => {
					return new Promise((resolve, reject) => {
						if (this.vuex_sign_image) {
							uni.uploadFile({
								url: `${ROOTPATH}/api/admin/upload-file`,
								header: {
									Authorization: `Bearer ${this.vuex_token}`
								},
								filePath: this.vuex_sign_image,
								name: 'file',
								success: (res) => {
									if (res.statusCode === 200) {
										const response = JSON.parse(res.data)
										resolve(response)
									} else {
										reject(res.data)
									}
								},
								fail: (err) => {
									reject(err)
								}
							})
						} else {
							resolve()
						}
					})
				}
				const uploadAdminSignImage = () => {
					return new Promise((resolve, reject) => {
						if (this.vuex_admin_sign_image) {
							uni.uploadFile({
								url: `${ROOTPATH}/api/admin/upload-file`,
								header: {
									Authorization: `Bearer ${this.vuex_token}`
								},
								filePath: this.vuex_admin_sign_image,
								name: 'file',
								success: (res) => {
									if (res.statusCode === 200) {
										const response = JSON.parse(res.data)
										resolve(response)
									} else {
										reject(res.data)
									}
								},
								fail: (err) => {
									reject(err)
								}
							})
						} else {
							resolve()
						}
					})
				}
				this.$refs.uForm.validate(valid => {
					if (valid) {
						Promise.all([uploadSignImage(), uploadAdminSignImage()]).then(res => {
							console.log(res)
							if (res[0]?.id) {
								this.form.sign_image_id = res[0].id
							}
							if (res[1]?.id) {
								this.form.admin_sign_image_id = res[1].id
							}
							this.form.file_ids = this.$refs.uUpload.lists.filter(i => i.progress === 100)
								.map(i => i.response?.id).filter(i => i)
							if (this.type === 'add') {
								delete this.form.id
							} else {
								this.form.id = this.id
							}
							this.$u.api.adminSaveQuality(this.form).then(res => {
								uni.showToast({
									icon: 'success',
									title: '保存成功',
								})
								setTimeout(() => {
									if(this.type==='edit'){
										uni.redirectTo({
											url:'/package_sub/pages/quality/qualityHistory'
										})
									}else{
									  uni.navigateBack()
									}
									
									this.$u.vuex('vuex_admin_sign_image', '')
									this.$u.vuex('vuex_sign_image', '')
								}, 1500)
							})
						}).catch(err => {
							console.error(err)
							uni.showToast({
								title: "签名保存失败",
								icon: "none"
							})
						})
					}
				})
			},

			async getDetail() {
				const res = await this.$u.api.adminQualityDetail(this.id)
				this.detail = res;
				for (let key in this.form) {
					this.form[key] = res[key]
				}
				this.form.customer_name = res.customer.name
				console.log(this.form)
				this.fileList = res.files.map(i => ({
					url: i.url,
					response: i
				}))
			}
		},
	}
</script>

<style lang="scss">
	.container {
		border-radius: 10rpx;
		background: #FFFFFF;
		box-shadow: 0rpx 4rpx 10rpx 0rpx rgba(219, 218, 218, 0.5);
		margin: 20rpx;
		padding: 20rpx;
	}

	.slot-btn {
		width: 200rpx;
		height: 200rpx;
		display: flex;
		justify-content: center;
		align-items: center;
		background: rgb(244, 245, 246);
		border: 2rpx #108cff solid;
		border-radius: 10rpx;
		box-sizing: content-box;
		filter: drop-shadow(0 0 4rpx #0fc7ff) drop-shadow(0 0 6rpx #00eaff);
	}

	.slot-btn__hover {
		background-color: rgb(235, 236, 238);
	}
</style>