<template>
	<view class="release-page">
		<view class="nav" :style="{ paddingTop: statusBarTop + 'px' }">
			<view class="back" @tap="back"><uni-icons type="left" size="23" color="#173b32"></uni-icons></view>
			<view>
				<view class="nav-title">{{isEdit ? '编辑校园圈' : '发布校园圈'}}</view>
				<view class="nav-sub">实名发布，内容和图片会进行安全审核</view>
			</view>
		</view>
		<scroll-view scroll-y class="form-scroll" :style="{ paddingTop: navHeight + 'px' }">
			<view class="type-tabs">
				<view class="type-tab" :class="{ active: form.postType === 'wall' }" @tap="chooseType('wall')">校园墙</view>
				<view class="type-tab" :class="{ active: form.partnerType === 'game' }" @tap="chooseType('game')">游戏搭子</view>
				<view class="type-tab" :class="{ active: form.partnerType === 'daily' }" @tap="chooseType('daily')">日常搭子</view>
				<view class="type-tab" :class="{ active: form.partnerType === 'sport' }" @tap="chooseType('sport')">运动搭子</view>
			</view>

			<view class="card">
				<view class="anonymous-row">
					<view>
						<view class="anonymous-title">匿名发布</view>
						<view class="anonymous-desc">开启后统一显示默认头像和“半径同学”</view>
					</view>
					<switch :checked="form.anonymous" color="#34c7a2" @change="toggleAnonymous" />
				</view>
				<view class="field">
					<view class="label">标题</view>
					<input v-model.trim="form.title" maxlength="30" placeholder="一句话说明你想发布的内容，最多30字" />
				</view>
				<view class="field">
					<view class="label">二级分类</view>
					<picker :range="categoryNames" @change="chooseCategory">
						<view class="picker-value">{{selectedCategoryName || '请选择分类'}} <text>›</text></view>
					</picker>
				</view>
				<view class="field">
					<view class="label">正文</view>
					<textarea v-model.trim="form.contentText" maxlength="1000" placeholder="友善真实地描述，禁止违规内容" />
				</view>
				<view class="field" v-if="form.postType === 'partner'">
					<view class="label">地点 <text>最多30字，可不填</text></view>
					<input v-model.trim="form.location" maxlength="30" placeholder="例如：东操场、图书馆三楼" />
				</view>
				<view class="field" v-if="form.postType === 'partner'">
					<view class="label">时间 <text>最多20字，可不填</text></view>
					<input v-model.trim="form.activityTime" maxlength="20" placeholder="例如：今晚8点、周末下午" />
				</view>
				<view class="field" v-if="form.postType === 'partner'">
					<view class="label">人数 <text>填写整数，可不填</text></view>
					<input v-model="form.targetCount" type="number" placeholder="期望人数，可不填" @input="onTargetCountInput" />
				</view>
				<view class="field" v-if="tagOptions.length">
					<view class="label">热门标签</view>
					<view class="tag-list">
						<view class="tag" :class="{ active: form.tags.indexOf(item.name) > -1 }" v-for="item in tagOptions" :key="item.key" @tap="toggleTag(item.name)">
							{{item.name}}
						</view>
					</view>
				</view>
				<view class="field">
					<view class="label">联系方式 <text>微信/手机号可选填</text></view>
					<input v-model.trim="form.contactWechat" maxlength="20" placeholder="微信号，可不填" />
					<input v-model.trim="form.contactPhone" type="number" maxlength="11" placeholder="手机号，可不填" @input="onContactPhoneInput" />
				</view>
				<view class="field">
					<view class="label">图片 <text>最多9张</text></view>
					<view class="image-list">
						<view class="image-item" v-for="(item,index) in form.images" :key="item">
							<image :src="item" mode="aspectFill"></image>
							<view class="remove" @tap="removeImage(index)">×</view>
						</view>
						<view class="image-add" v-if="form.images.length < 9" hover-class="none" @tap.stop="chooseImages" @click.stop="chooseImages">
							<uni-icons type="plusempty" size="28" color="#7d918c"></uni-icons>
							<text>上传</text>
						</view>
					</view>
					<view class="audit-inline" :class="{ fail: imageAuditStatus === 'fail' }" v-if="imageAuditing || imageAuditMessage">
						<view class="mini-spinner" v-if="imageAuditing"></view>
						<text>{{imageAuditing ? '图片审核中，请稍候...' : imageAuditMessage}}</text>
					</view>
				</view>
			</view>
			<view class="safe-tip">发布、评论和聊天都会进行内容审核，违规内容会记录用于审核计费和后台治理。</view>
			<view class="audit-inline form-audit" :class="{ fail: formAuditStatus === 'fail' }" v-if="formAuditMessage && !submitting">
				<text>{{formAuditMessage}}</text>
			</view>
			<view class="bottom-space"></view>
		</scroll-view>

		<view class="submit-bar">
			<view class="submit-btn" :class="{ disabled: submitting }" @tap="submit">{{submitting ? '提交审核中...' : '提交发布'}}</view>
		</view>
		<view class="audit-mask" v-if="submitting">
			<view class="audit-card">
				<view class="spinner"></view>
				<view class="audit-title">表单内容审核中</view>
				<view class="audit-desc">图片、标题和正文正在审核，请勿重复点击或退出页面</view>
			</view>
		</view>
		<ie-auth-dialog />
	</view>
</template>

<script>
	import { getIeProfile } from '@/common/ieApi.js'
	import { ensureIeVerifiedBeforeAction } from '@/common/ieRealNameAuth.js'
	import {
		listCampusCategories,
		getCampusPostDetail,
		publishCampusPost,
		uploadCampusReleaseImage
	} from '@/common/campusApi.js'
	import IeAuthDialog from '@/package1/components/ie-auth-dialog/ie-auth-dialog.vue'

	export default {
		components: { IeAuthDialog },
		data() {
			return {
				statusBarTop: 24,
				editId: '',
				isEdit: false,
				categories: [],
				tags: [],
				selectedCategoryIndex: -1,
				submitting: false,
				submitLocked: false,
				imageChoosing: false,
				imageAuditing: false,
				imageAuditStatus: '',
				imageAuditMessage: '',
				formAuditStatus: '',
				formAuditMessage: '',
				form: {
					postType: 'wall',
					partnerType: '',
					title: '',
					categoryId: '',
					categoryName: '',
					content: '',
					contentText: '',
					images: [],
					tags: [],
					location: '',
					activityTime: '',
					targetCount: '',
					contactWechat: '',
					contactPhone: '',
					anonymous: false
				}
			}
		},
		computed: {
			navHeight() {
				return this.statusBarTop + uni.upx2px(120)
			},
			currentParentCode() {
				return this.form.postType === 'wall' ? 'wall' : this.form.partnerType
			},
			categoryNames() {
				return this.categories.map(item => item.name)
			},
			selectedCategoryName() {
				const item = this.categories[this.selectedCategoryIndex]
				return item ? item.name : ''
			},
			tagOptions() {
				return this.tags
					.filter(item => item.parentCode === this.currentParentCode)
					.map((item, index) => ({
						...item,
						key: item.id || item.code || item.name || String(index)
					}))
			}
		},
		onLoad(options = {}) {
			if (options.type && options.type !== 'wall') this.chooseType(options.type)
			if (options.id) {
				this.editId = options.id
				this.isEdit = true
			}
			if (uni.getMenuButtonBoundingClientRect) {
				this.statusBarTop = uni.getMenuButtonBoundingClientRect().top || this.statusBarTop
			}
			this.loadMeta()
			if (this.isEdit) this.loadEditDetail()
			this.ensureVerified(true)
		},
		methods: {
			back() {
				uni.navigateBack()
			},
			getArea() {
				const area = uni.getStorageSync('area')
				if (!area) return {}
				if (typeof area === 'string') {
					try { return JSON.parse(area) } catch (e) { return {} }
				}
				return area
			},
			chooseType(type) {
				if (type === 'wall') {
					this.form.postType = 'wall'
					this.form.partnerType = ''
				} else {
					this.form.postType = 'partner'
					this.form.partnerType = type
				}
				this.selectedCategoryIndex = -1
				this.form.categoryId = ''
				this.form.categoryName = ''
				this.form.tags = []
				this.loadMeta()
			},
			loadMeta() {
				const area = this.getArea()
				Promise.all([
					listCampusCategories({ regionId: area.id || '', parentCode: this.currentParentCode, categoryType: 'category' }),
					listCampusCategories({ regionId: area.id || '', categoryType: 'tag' })
				]).then(([categories, tags]) => {
					this.categories = Array.isArray(categories) ? categories : []
					this.tags = Array.isArray(tags) ? tags : []
					this.applyEditCategory()
				})
			},
			loadEditDetail() {
				getCampusPostDetail(this.editId).then(detail => {
					if (!detail) return
					this.form = {
						...this.form,
						postType: detail.postType || 'wall',
						partnerType: detail.partnerType || '',
						title: detail.title || '',
						categoryId: detail.categoryId || '',
						categoryName: detail.categoryName || '',
						content: detail.content || detail.contentText || '',
						contentText: detail.contentText || '',
						images: detail.imageList || [],
						tags: detail.tagList || [],
						location: detail.location || '',
						activityTime: detail.activityTime || '',
						targetCount: detail.targetCount || '',
						contactWechat: detail.contactWechat || '',
						contactPhone: detail.contactPhone || '',
						anonymous: detail.userName === '半径同学' && !detail.userAvatar
					}
					this.applyEditCategory()
				})
			},
			applyEditCategory() {
				if (!this.form.categoryId || !this.categories.length) return
				this.selectedCategoryIndex = this.categories.findIndex(item => item.id === this.form.categoryId)
			},
			chooseCategory(e) {
				const index = Number(e.detail.value)
				const item = this.categories[index]
				if (!item) return
				this.selectedCategoryIndex = index
				this.form.categoryId = item.id
				this.form.categoryName = item.name
			},
			toggleTag(tag) {
				const index = this.form.tags.indexOf(tag)
				if (index > -1) this.form.tags.splice(index, 1)
				else this.form.tags.push(tag)
			},
			toggleAnonymous(e) {
				this.form.anonymous = !!(e && e.detail && e.detail.value)
			},
			onTargetCountInput(e) {
				const value = String((e && e.detail && e.detail.value) || '').replace(/[^\d]/g, '')
				this.form.targetCount = value
				return value
			},
			onContactPhoneInput(e) {
				const value = String((e && e.detail && e.detail.value) || '').replace(/[^\d]/g, '').slice(0, 11)
				this.form.contactPhone = value
				return value
			},
			chooseImages() {
				if (this.imageChoosing || this.imageAuditing) return
				this.imageChoosing = true
				this.imageAuditStatus = ''
				this.imageAuditMessage = ''
				uni.chooseImage({
					count: 9 - this.form.images.length,
					sizeType: ['compressed'],
					success: async res => {
						const paths = res.tempFilePaths || []
						if (!paths.length) return
						this.imageAuditing = true
						try {
							for (const path of paths) {
								const audit = await uploadCampusReleaseImage(path)
								if (audit && audit.passed && audit.url) {
									this.form.images.push(audit.url)
								} else {
									this.imageAuditStatus = 'fail'
									this.imageAuditMessage = '图片审核不通过：' + ((audit && audit.message) || '请更换图片后重试')
									uni.showToast({ title: this.imageAuditMessage, icon: 'none', duration: 3000 })
									break
								}
							}
							if (this.imageAuditStatus !== 'fail') {
								this.imageAuditMessage = ''
							}
						} catch (e) {
							this.imageAuditStatus = 'fail'
							this.imageAuditMessage = '图片审核失败，请稍后重试'
							uni.showToast({ title: this.imageAuditMessage, icon: 'none', duration: 3000 })
						} finally {
							this.imageAuditing = false
						}
					},
					fail: err => {
						if (err && err.errMsg && err.errMsg.indexOf('cancel') === -1) {
							uni.showToast({ title: '无法选择图片，请检查相册权限', icon: 'none' })
						}
					},
					complete: () => {
						this.imageChoosing = false
					}
				})
			},
			removeImage(index) {
				this.form.images.splice(index, 1)
			},
			validate() {
				this.form.title = (this.form.title || '').trim()
				this.form.contentText = (this.form.contentText || '').trim()
				this.form.location = (this.form.location || '').trim()
				this.form.activityTime = (this.form.activityTime || '').trim()
				this.form.targetCount = String(this.form.targetCount || '').trim()
				this.form.contactWechat = (this.form.contactWechat || '').trim()
				this.form.contactPhone = String(this.form.contactPhone || '').trim()
				if (!this.form.title) return '请填写标题'
				if (this.form.title.length > 30) return '标题不能超过30字'
				if (!this.form.categoryId) return '请选择二级分类'
				if (this.imageAuditing) return '图片正在审核中，请稍候'
				if (this.form.contentText.length > 1000) return '正文不能超过1000字'
				if (this.form.postType === 'partner' && !this.form.partnerType) return '请选择搭子类型'
				if (this.form.location.length > 30) return '地点不能超过30字'
				if (this.form.activityTime.length > 20) return '时间不能超过20字'
				if (this.form.targetCount && (!/^\d+$/.test(this.form.targetCount) || Number(this.form.targetCount) < 1)) return '人数请填写正整数'
				if (this.form.contactWechat && !/^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/.test(this.form.contactWechat)) return '微信号格式不正确'
				if (this.form.contactPhone && !/^1[3-9]\d{9}$/.test(this.form.contactPhone)) return '手机号格式不正确'
				return ''
			},
			goReleaseHome() {
				uni.redirectTo({
					url: '/package1/tabbar/release',
					fail: () => uni.navigateBack()
				})
			},
			async ensureVerified(redirectOnFail = false) {
				const profile = await getIeProfile().catch(() => null)
				const ok = await ensureIeVerifiedBeforeAction({
					profile: profile || {},
					actionText: '发布校园圈内容',
					authDialog: { badge: '校园圈', title: '实名认证', desc: '发布、评论和聊天前需要完成实名认证' },
					reload: getIeProfile
				})
				if (!ok && redirectOnFail) {
					setTimeout(() => this.goReleaseHome(), 120)
				}
				return ok
			},
			async submit() {
				if (this.submitLocked || this.submitting) return
				const error = this.validate()
				if (error) {
					uni.showToast({ title: error, icon: 'none' })
					return
				}
				const verified = await this.ensureVerified(true)
				if (!verified) return
				this.submitLocked = true
				this.submitting = true
				this.formAuditStatus = ''
				this.formAuditMessage = ''
				const area = this.getArea()
				publishCampusPost({
					id: this.editId || undefined,
					regionId: area.id || '',
					regionName: area.name || area.title || '',
					...this.getSubmitUserProfile(),
					...this.form,
					content: this.form.contentText,
					targetCount: this.form.targetCount ? Number(this.form.targetCount) : undefined
				}).then(post => {
					if (!post) throw new Error('发布失败')
					const publishedAt = Date.now()
					uni.setStorageSync('campusPostPublishedAt', publishedAt)
					uni.$emit('campusPostPublished', { id: post.id || this.editId || '', publishedAt })
					uni.$emit('campusUnreadChange')
					uni.showToast({ title: '发布成功', icon: 'success' })
					setTimeout(() => uni.navigateBack(), 600)
				}).catch(err => {
					this.submitLocked = false
					const message = (err && err.message) || '发布失败，请稍后重试'
					this.formAuditStatus = 'fail'
					this.formAuditMessage = message.indexOf('审核') > -1 || message.indexOf('违规') > -1
						? '表单审核不通过：' + message
						: message
					uni.showToast({ title: this.formAuditMessage, icon: 'none', duration: 3000 })
				}).finally(() => {
					this.submitting = false
				})
			},
			getSubmitUserProfile() {
				if (this.form.anonymous) {
					return {
						userName: '半径同学',
						userAvatar: ''
					}
				}
				return {
					userName: uni.getStorageSync('nickName') || uni.getStorageSync('nickname') || uni.getStorageSync('userName') || '',
					userAvatar: uni.getStorageSync('avatar') || uni.getStorageSync('avatarUrl') || uni.getStorageSync('headimgurl') || ''
				}
			}
		}
	}
</script>

<style scoped>
	.release-page { position: relative; min-height: 100vh; overflow: hidden; background: radial-gradient(circle at 12% 8%, rgba(68, 224, 186, .32), transparent 260rpx), radial-gradient(circle at 88% 18%, rgba(93, 175, 255, .18), transparent 300rpx), linear-gradient(180deg, #effff9 0%, #f7fbfa 44%, #ffffff 100%); }
	.release-page::before { content: ''; position: fixed; right: -130rpx; top: 210rpx; z-index: 0; width: 280rpx; height: 280rpx; border-radius: 50%; background: rgba(44, 211, 175, .16); filter: blur(10rpx); pointer-events: none; animation: releaseGlow 4s ease-in-out infinite; }
	.release-page::after { content: ''; position: fixed; left: -150rpx; bottom: 220rpx; z-index: 0; width: 320rpx; height: 320rpx; border-radius: 50%; background: rgba(58, 214, 166, .08); filter: blur(12rpx); pointer-events: none; animation: releaseGlow 5s ease-in-out infinite reverse; }
	.nav { position: fixed; left: 0; right: 0; top: 0; z-index: 10; padding: 20rpx 28rpx 24rpx; display: flex; align-items: center; gap: 18rpx; background: linear-gradient(180deg, rgba(237, 255, 249, .98), rgba(247, 255, 252, .94)); box-shadow: 0 10rpx 28rpx rgba(31, 120, 94, .07); }
	.back { width: 68rpx; height: 68rpx; border-radius: 50%; background: rgba(255,255,255,.88); display: flex; align-items: center; justify-content: center; box-shadow: 0 10rpx 24rpx rgba(34, 100, 82, .10); }
	.nav-title { font-size: 36rpx; font-weight: 900; color: #173b32; letter-spacing: -1rpx; }
	.nav-sub { font-size: 22rpx; color: #6f817c; margin-top: 6rpx; }
	.form-scroll { height: 100vh; box-sizing: border-box; }
	.type-tabs { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 14rpx; padding: 30rpx 26rpx 24rpx; }
	.type-tab { padding: 20rpx 8rpx; border-radius: 24rpx; background: rgba(255,255,255,.82); color: #546861; text-align: center; font-size: 24rpx; font-weight: 700; box-shadow: 0 10rpx 24rpx rgba(34, 82, 73, .06); border: 2rpx solid rgba(255,255,255,.8); }
	.type-tab.active { background: linear-gradient(135deg, #34d8ad, #25c6c5); color: #fff; font-weight: 900; box-shadow: 0 14rpx 30rpx rgba(38, 196, 169, .24); }
	.card { position: relative; z-index: 1; margin: 0 24rpx; padding: 28rpx 26rpx 18rpx; background: rgba(255,255,255,.94); border-radius: 34rpx; box-shadow: 0 18rpx 42rpx rgba(40, 84, 75, .10); border: 1rpx solid rgba(255,255,255,.9); backdrop-filter: blur(8rpx); }
	.anonymous-row { display: flex; align-items: center; justify-content: space-between; padding: 0 0 26rpx; border-bottom: 1rpx solid #edf4f1; }
	.anonymous-title { color: #263d38; font-size: 28rpx; font-weight: 900; }
	.anonymous-desc { margin-top: 8rpx; color: #94a39e; font-size: 22rpx; }
	.field { padding: 28rpx 0; border-bottom: 1rpx solid #edf4f1; }
	.field:last-child { border-bottom: 0; }
	.label { font-size: 28rpx; font-weight: 900; color: #263d38; margin-bottom: 18rpx; }
	.label text { color: #94a39e; font-size: 22rpx; font-weight: 400; }
	input, textarea { width: 100%; box-sizing: border-box; font-size: 26rpx; color: #263d38; background: #f6fbf9; border-radius: 22rpx; padding: 0 22rpx; margin-bottom: 16rpx; border: 1rpx solid rgba(225, 238, 234, .9); box-shadow: inset 0 2rpx 0 rgba(255,255,255,.8); }
	input { height: 72rpx; line-height: 72rpx; }
	textarea { height: 260rpx; padding-top: 20rpx; line-height: 1.6; }
	.picker-value { min-height: 72rpx; background: #f6fbf9; border-radius: 22rpx; padding: 0 22rpx; color: #526761; display: flex; align-items: center; justify-content: space-between; border: 1rpx solid rgba(225, 238, 234, .9); }
	.tag-list { display: flex; flex-wrap: wrap; gap: 12rpx; }
	.tag { padding: 12rpx 20rpx; border-radius: 999rpx; background: #eef7f4; color: #526761; font-size: 23rpx; font-weight: 700; }
	.tag.active { background: linear-gradient(135deg, #34d8ad, #25c6c5); color: #fff; box-shadow: 0 8rpx 18rpx rgba(38, 196, 169, .18); }
	.image-list { position: relative; z-index: 2; display: flex; flex-wrap: wrap; gap: 14rpx; }
	.image-item, .image-add { width: 154rpx; height: 154rpx; border-radius: 22rpx; overflow: hidden; position: relative; background: #f3f8f6; display: flex; flex-direction: column; align-items: center; justify-content: center; color: #7d918c; font-size: 22rpx; box-shadow: none; }
	.image-add { border: 2rpx dashed #d8e6e1; background: #f8fbfa; color: #788b86; }
	.image-add:active { background: #eef7f3; }
	.image-add text { margin-top: 6rpx; }
	.image-item image { width: 100%; height: 100%; }
	.remove { position: absolute; right: 8rpx; top: 8rpx; width: 34rpx; height: 34rpx; line-height: 34rpx; text-align: center; background: rgba(0,0,0,.5); color: #fff; border-radius: 50%; }
	.audit-inline { display: flex; align-items: center; gap: 10rpx; margin-top: 18rpx; padding: 16rpx 18rpx; border-radius: 18rpx; background: #effbf7; color: #2c8b72; font-size: 23rpx; line-height: 1.45; }
	.audit-inline.fail { background: #fff1ef; color: #d64b3c; }
	.form-audit { position: relative; z-index: 1; margin: 18rpx 30rpx 0; }
	.mini-spinner { width: 26rpx; height: 26rpx; flex: 0 0 26rpx; border-radius: 50%; border: 4rpx solid #c9f2e8; border-top-color: #2fc49f; animation: spin .8s linear infinite; }
	.safe-tip { position: relative; z-index: 1; margin: 24rpx 30rpx; padding: 18rpx 22rpx; border-radius: 22rpx; background: rgba(235, 250, 246, .86); color: #6f837d; font-size: 23rpx; line-height: 1.6; }
	.bottom-space { height: 160rpx; }
	.submit-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; padding: 20rpx 28rpx 34rpx; background: rgba(255,255,255,.98); box-shadow: 0 -8rpx 28rpx rgba(31, 67, 59, .08); }
	.submit-btn { height: 92rpx; line-height: 92rpx; text-align: center; border-radius: 999rpx; background: linear-gradient(135deg, #34d8ad, #25c6c5); color: #fff; font-size: 30rpx; font-weight: 900; box-shadow: 0 14rpx 30rpx rgba(38, 196, 169, .28); }
	.submit-btn.disabled { opacity: .65; }
	.audit-mask { position: fixed; inset: 0; z-index: 50; background: rgba(20, 35, 31, .45); display: flex; align-items: center; justify-content: center; }
	.audit-card { width: 440rpx; padding: 44rpx 34rpx; border-radius: 32rpx; background: #fff; text-align: center; }
	.spinner { width: 54rpx; height: 54rpx; margin: 0 auto 20rpx; border-radius: 50%; border: 6rpx solid #d8f5ee; border-top-color: #34c7a2; animation: spin .8s linear infinite; }
	.audit-title { font-size: 30rpx; font-weight: 800; color: #183a32; }
	.audit-desc { margin-top: 10rpx; color: #788883; font-size: 24rpx; }
	@keyframes spin { to { transform: rotate(360deg); } }
	@keyframes releaseGlow { 0%, 100% { transform: scale(.92); opacity: .65; } 50% { transform: scale(1.08); opacity: 1; } }
</style>
