<template>
	<view class="release-page">
		<view class="header" :style="{ paddingTop: statusBarTop + 'px' }">
			<view class="back" @tap="back">
				<uni-icons type="left" size="22" color="#18372f"></uni-icons>
			</view>
			<view class="header-title">发布校园二手</view>
			<view class="header-sub">实名发布，线下面交，请勿提前转账</view>
			<view class="tabs">
				<view class="tab" :class="{ active: publishType == 'sell' }" @tap="switchType('sell')">出售</view>
				<view class="tab" :class="{ active: publishType == 'want' }" @tap="switchType('want')">求购</view>
			</view>
		</view>

		<view class="form-scroll" :style="{ paddingTop: headerHeight + 'px' }">
			<view class="form-card">
				<view class="field" id="fieldTitle">
					<view class="label">标题</view>
					<input v-model.trim="form.title" maxlength="10" placeholder="最多10个字" />
				</view>

				<view class="field price-row" id="fieldPrice">
					<view class="price-field">
						<view class="label">{{publishType == 'sell' ? '售价' : '预算'}}</view>
						<input v-model="form.price" type="digit" placeholder="0.00" />
					</view>
					<view class="price-field" v-if="publishType == 'sell'">
						<view class="label">原价</view>
						<input v-model="form.originPrice" type="digit" placeholder="可不填" />
					</view>
				</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">图片 <text>{{publishType == 'sell' ? '最多9张' : '最多1张，可选'}}</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 < maxImageCount" @tap="chooseImages">
							<uni-icons type="plusempty" size="28" color="#8aa09a"></uni-icons>
							<text>上传</text>
						</view>
					</view>
				</view>

				<view class="field" id="fieldContent">
					<view class="label">{{publishType == 'sell' ? '商品介绍' : '求购内容'}}</view>
					<view class="editor-box">
						<sp-editor
							editor-id="fishReleaseEditor"
							:toolbar-config="editorToolbarConfig"
							:maxlength="2000"
							:placeholder="publishType == 'sell' ? '描述成色、尺寸、交易地点、可取时间等' : '描述想要的物品、预算、交易地点、可取时间等'"
							@init="initEditor"
							@input="inputEditor"
							@upinImage="upinEditorImage"
							@overMax="overEditorMax"
						></sp-editor>
					</view>
				</view>

				<view class="field" id="fieldContact">
					<view class="label">联系方式</view>
					<input v-model.trim="form.wechat" maxlength="20" placeholder="微信号，可选" cursor-spacing="180" />
					<input v-model.trim="form.phone" class="contact-input" maxlength="11" type="number" placeholder="手机号，可选" cursor-spacing="180" />
				</view>

				<view class="field" v-if="publishType == 'sell'">
					<view class="label">商品标签</view>
					<view class="tag-list">
						<view class="tag" :class="{ checked: form.tags.indexOf(item) > -1 }" v-for="item in tagOptions" :key="item" @tap="toggleTag(item)">
							{{item}}
						</view>
					</view>
				</view>
			</view>

			<view class="safe-tip">发布内容、图片、评论都会进行内容安全审核。可以留电话或微信，但请线下面交，谨防诈骗。</view>
			<view class="bottom-space"></view>
		</view>

		<view class="submit-bar" v-if="!keyboardOpen">
			<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="audit-spinner">
					<view></view>
					<view></view>
					<view></view>
				</view>
				<view class="audit-title">{{auditTitle}}</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 IeAuthDialog from '@/package1/components/ie-auth-dialog/ie-auth-dialog.vue'
	import SpEditor from '@/package1/components/sp-editor/components/sp-editor/sp-editor.vue'
	import {
		listFishCategories,
		publishFishGoods,
		publishFishWant,
		uploadFishImage
	} from '@/common/fishMarketApi.js'

	export default {
		components: {
			IeAuthDialog,
			SpEditor
		},
		data() {
			return {
				statusBarTop: 24,
				publishType: 'sell',
				categories: [],
				selectedCategoryIndex: -1,
				submitting: false,
				submitLocked: false,
				keyboardOpen: false,
				auditTitle: '提交中，等待审核',
				editorIns: null,
				editorToolbarConfig: {
					keys: ['bold', 'italic', 'underline', 'header', 'listOrdered', 'listBullet', 'align', 'image', 'removeFormat', 'clear'],
					iconSize: '17px',
					iconColumns: 10
				},
				tagOptions: ['可小刀', '当天可取', '宿舍自提', '可送宿舍', '急出', '九成新'],
				form: {
					title: '',
					price: '',
					originPrice: '',
					content: '',
					contentText: '',
					images: [],
					wechat: '',
					phone: '',
					tags: ['可小刀']
				}
			}
		},
		computed: {
			categoryNames() {
				return this.categories.map(item => item.name)
			},
			selectedCategoryName() {
				const item = this.categories[this.selectedCategoryIndex]
				return item ? item.name : ''
			},
			maxImageCount() {
				return this.publishType == 'sell' ? 9 : 1
			},
			headerHeight() {
				return this.statusBarTop + uni.upx2px(300)
			}
		},
		onLoad(options) {
			if (options && (options.type == 'want' || options.type == 'sell')) {
				this.publishType = options.type
			}
			if (uni.getMenuButtonBoundingClientRect) {
				this.statusBarTop = uni.getMenuButtonBoundingClientRect().top || this.statusBarTop
			}
			this.loadCategories()
			this.ensurePublishVerified()
			this.bindKeyboardListener()
		},
		onUnload() {
			if (uni.offKeyboardHeightChange) {
				uni.offKeyboardHeightChange()
			}
		},
		methods: {
			bindKeyboardListener() {
				if (!uni.onKeyboardHeightChange) return
				uni.onKeyboardHeightChange((res) => {
					this.keyboardOpen = Number(res && res.height) > 0
				})
			},
			back() {
				uni.navigateBack({ fail: () => uni.switchTab({ url: '/pages/index/index' }) })
			},
			switchType(type) {
				this.publishType = type
				if (type == 'want' && this.form.images.length > 1) {
					this.form.images = this.form.images.slice(0, 1)
				}
			},
			getArea() {
				const area = uni.getStorageSync('area')
				if (!area) return {}
				if (typeof area === 'string') {
					try {
						return JSON.parse(area)
					} catch (e) {
						return {}
					}
				}
				return area
			},
			loadCategories() {
				const area = this.getArea()
				listFishCategories(area.id || '').then(list => {
					this.categories = Array.isArray(list) ? list : []
				})
			},
			async ensurePublishVerified() {
				const profile = await getIeProfile().catch(() => null)
				const verified = await ensureIeVerifiedBeforeAction({
					profile: profile || {},
					actionText: '发布校园二手信息',
					authDialog: this.fishAuthDialogOptions(),
					reload: getIeProfile
				})
				if (!verified) {
					setTimeout(() => this.back(), 300)
				}
			},
			chooseCategory(e) {
				this.selectedCategoryIndex = Number(e.detail.value)
			},
			chooseImages() {
				const remain = this.maxImageCount - this.form.images.length
				if (remain <= 0) return
				uni.chooseImage({
					count: remain,
					sizeType: ['compressed'],
					sourceType: ['album', 'camera'],
					success: async (res) => {
						const paths = res.tempFilePaths || []
						uni.showLoading({ title: '上传中...', mask: true })
						try {
							for (let i = 0; i < paths.length; i++) {
								const url = await uploadFishImage(paths[i])
								if (url) this.form.images.push(url)
							}
						} finally {
							uni.hideLoading()
						}
					}
				})
			},
			removeImage(index) {
				this.form.images.splice(index, 1)
			},
			initEditor(editor) {
				this.editorIns = editor
			},
			inputEditor(e) {
				this.form.content = e && e.html ? e.html : ''
				this.form.contentText = e && e.text ? e.text : ''
			},
			overEditorMax() {
				uni.showToast({ title: '内容最多2000字', icon: 'none' })
			},
			async upinEditorImage(tempFiles, editorCtx) {
				const files = Array.isArray(tempFiles) ? tempFiles : []
				if (!files.length || !editorCtx) return
				uni.showLoading({ title: '上传中...', mask: true })
				try {
					for (let i = 0; i < files.length; i++) {
						const filePath = files[i].tempFilePath || files[i].path
						const url = filePath ? await uploadFishImage(filePath) : ''
						if (url) {
							editorCtx.insertImage({
								src: url,
								width: '90%'
							})
						}
					}
				} finally {
					uni.hideLoading()
				}
			},
			toggleTag(tag) {
				const index = this.form.tags.indexOf(tag)
				if (index > -1) {
					this.form.tags.splice(index, 1)
				} else {
					this.form.tags.push(tag)
				}
			},
			syncEditorContent() {
				return new Promise((resolve) => {
					if (!this.editorIns || !this.editorIns.getContents) {
						resolve()
						return
					}
					this.editorIns.getContents({
						success: (res) => {
							this.form.content = res.html || this.form.content || ''
							this.form.contentText = res.text || this.form.contentText || ''
							resolve()
						},
						fail: () => resolve()
					})
				})
			},
			validate() {
				const title = String(this.form.title || '').trim()
				const price = String(this.form.price || '').trim()
				const originPrice = String(this.form.originPrice || '').trim()
				const contentText = String(this.form.contentText || '').replace(/[ \t\r\n]/g, '')
				const wechat = String(this.form.wechat || '').trim()
				const phone = String(this.form.phone || '').trim()
				if (!title) return '请填写标题'
				if (title.length < 2) return '标题至少2个字'
				if (title.length > 10) return '标题最多10个字'
				if (this.selectedCategoryIndex < 0) return '请选择分类'
				if (!price) return this.publishType == 'sell' ? '请填写售价' : '请填写预算'
				if (!this.isValidPrice(price)) return this.publishType == 'sell' ? '售价必须大于0且最多2位小数' : '预算必须大于0且最多2位小数'
				if (originPrice && !this.isValidAmount(originPrice)) return '原价最多2位小数'
				if (this.publishType == 'sell' && this.form.images.length == 0) return '请至少上传1张商品图片'
				if (this.publishType == 'want' && this.form.images.length > 1) return '求购最多上传1张图片'
				if (!contentText) return this.publishType == 'sell' ? '请填写商品介绍' : '请填写求购内容'
				if (contentText.length < 5) return this.publishType == 'sell' ? '商品介绍至少5个字' : '求购内容至少5个字'
				if (!wechat && !phone) return '请至少填写一种联系方式'
				if (wechat && !this.isValidWechat(wechat)) return '请输入正确的微信号'
				if (phone && !this.isValidPhone(phone)) return '请输入正确的手机号'
				return ''
			},
			isValidPrice(value) {
				return /^\d+(\.\d{1,2})?$/.test(value) && Number(value) > 0
			},
			isValidAmount(value) {
				return /^\d+(\.\d{1,2})?$/.test(value) && Number(value) >= 0
			},
			isValidWechat(value) {
				return /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/.test(value)
			},
			isValidPhone(value) {
				return /^1[3-9]\d{9}$/.test(value)
			},
			async submit() {
				if (this.submitLocked) return
				this.submitLocked = true
				let submitSuccess = false
				try {
					await this.syncEditorContent()
					const error = this.validate()
					if (error) {
						uni.showToast({ title: error, icon: 'none' })
						return
					}
					const profile = await getIeProfile().catch(() => null)
					const verified = await ensureIeVerifiedBeforeAction({
						profile: profile || {},
						actionText: '发布校园二手信息',
						authDialog: this.fishAuthDialogOptions(),
						reload: getIeProfile
					})
					if (!verified) return
					const area = this.getArea()
					const category = this.categories[this.selectedCategoryIndex]
					const payload = {
						publishType: this.publishType,
						regionId: area.id || '',
						regionName: area.title || '',
						title: this.form.title,
						content: this.form.content,
						price: this.publishType == 'sell' ? Number(this.form.price) : undefined,
						originPrice: this.form.originPrice ? Number(this.form.originPrice) : undefined,
						expectedPrice: this.publishType == 'want' ? Number(this.form.price) : undefined,
						categoryId: category.id,
						categoryName: category.name,
						images: this.publishType == 'want' ? this.form.images.slice(0, 1) : this.form.images,
						contactInfo: {
							wechat: this.form.wechat,
							phone: this.form.phone
						},
						tags: this.form.tags,
						negotiable: this.form.tags.indexOf('可小刀') > -1 ? 1 : 0
					}
					this.submitting = true
					this.auditTitle = '提交中，等待审核'
					const res = this.publishType == 'sell' ? await publishFishGoods(payload) : await publishFishWant(payload)
					if (res) {
						submitSuccess = true
						this.auditTitle = '提交成功，等待审核'
						setTimeout(() => uni.navigateBack(), 800)
					}
				} finally {
					if (!submitSuccess) {
						this.submitting = false
						this.submitLocked = false
					}
				}
			},
			fishAuthDialogOptions() {
				return {
					badge: '校园二手',
					title: '实名认证',
					content: '根据法律法规要求，对应流程需要实名认证。',
					steps: []
				}
			}
		}
	}
</script>

<style lang="scss">
	page {
		background: #f7f9f7;
		color: #15362f;
	}

	.release-page {
		min-height: 100vh;
		overflow: visible;
		background: linear-gradient(180deg, #e7fbf4 0%, #f7f9f7 280rpx);
	}

	.header {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		z-index: 20;
		padding: 0 32rpx 28rpx;
		background: linear-gradient(180deg, #e7fbf4 0%, rgba(247, 249, 247, 0.98) 100%);
		box-shadow: 0 8rpx 24rpx rgba(24, 99, 78, 0.05);
		box-sizing: border-box;
	}

	.back {
		width: 64rpx;
		height: 64rpx;
		display: flex;
		align-items: center;
	}

	.header-title {
		margin-top: 12rpx;
		font-size: 42rpx;
		font-weight: 900;
	}

	.header-sub {
		margin-top: 8rpx;
		color: #729088;
		font-size: 24rpx;
	}

	.form-scroll {
		box-sizing: border-box;
	}

	.tabs {
		width: 360rpx;
		height: 72rpx;
		margin: 26rpx 0 0;
		padding: 6rpx;
		display: flex;
		border-radius: 42rpx;
		background: rgba(255, 255, 255, 0.86);
		box-sizing: border-box;
	}

	.tab {
		flex: 1;
		height: 60rpx;
		line-height: 60rpx;
		border-radius: 34rpx;
		text-align: center;
		font-size: 26rpx;
		font-weight: 800;
		color: #7c8d88;
	}

	.tab.active {
		background: linear-gradient(135deg, #39ca8f, #24b979);
		color: #fff;
		box-shadow: 0 8rpx 18rpx rgba(36, 185, 121, 0.22);
	}

	.form-card {
		margin: 0 24rpx;
		padding: 4rpx 26rpx 26rpx;
		border-radius: 30rpx;
		background: #fff;
		box-shadow: 0 12rpx 32rpx rgba(29, 74, 60, 0.06);
	}

	.field {
		padding-top: 26rpx;
	}

	.label {
		margin-bottom: 14rpx;
		color: #18372f;
		font-size: 27rpx;
		font-weight: 900;
	}

	.label text {
		color: #9aa8a4;
		font-size: 21rpx;
		font-weight: 400;
	}

	input,
	textarea,
	.picker-value {
		width: 100%;
		min-height: 78rpx;
		padding: 0 22rpx;
		border-radius: 18rpx;
		background: #f5f8f6;
		box-sizing: border-box;
		color: #223b35;
		font-size: 26rpx;
	}

	textarea {
		height: 220rpx;
		padding-top: 20rpx;
		line-height: 38rpx;
	}

	.editor-box {
		min-height: 420rpx;
		overflow: hidden;
		border-radius: 18rpx;
		background: #f5f8f6;
		border: 1rpx solid #edf2ef;
		box-sizing: border-box;
	}

	.editor-box ::v-deep .sp-editor-toolbar {
		background: #fff;
		border-bottom: 1rpx solid #edf2ef;
	}

	.editor-box ::v-deep .sp-editor-wrapper {
		min-height: 320rpx;
	}

	.editor-box ::v-deep .editor-container {
		min-height: 320rpx;
		padding: 18rpx 20rpx;
		box-sizing: border-box;
		font-size: 26rpx;
		line-height: 40rpx;
	}

	.picker-value {
		line-height: 78rpx;
	}

	.picker-value text {
		float: right;
		color: #8ca09a;
		font-size: 34rpx;
	}

	.price-row {
		display: flex;
		gap: 18rpx;
	}

	.price-field {
		flex: 1;
	}

	.image-list {
		display: flex;
		flex-wrap: wrap;
		gap: 14rpx;
	}

	.image-item,
	.image-add {
		position: relative;
		width: 150rpx;
		height: 150rpx;
		border-radius: 18rpx;
		overflow: hidden;
		background: #f2f7f4;
	}

	.image-item image {
		width: 100%;
		height: 100%;
	}

	.remove {
		position: absolute;
		top: 8rpx;
		right: 8rpx;
		width: 34rpx;
		height: 34rpx;
		border-radius: 50%;
		background: rgba(0, 0, 0, 0.48);
		color: #fff;
		text-align: center;
		line-height: 30rpx;
	}

	.image-add {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		color: #8aa09a;
		font-size: 22rpx;
	}

	.contact-input {
		margin-top: 14rpx;
	}

	.tag-list {
		display: flex;
		flex-wrap: wrap;
		gap: 14rpx;
	}

	.tag {
		height: 56rpx;
		padding: 0 20rpx;
		border-radius: 28rpx;
		background: #f2f6f4;
		color: #6f817c;
		font-size: 23rpx;
		line-height: 56rpx;
	}

	.tag.checked {
		background: #e5fbf2;
		color: #1a9a72;
		font-weight: 800;
	}

	.safe-tip {
		margin: 22rpx 32rpx 0;
		color: #84948f;
		font-size: 22rpx;
		line-height: 34rpx;
	}

	.submit-bar {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		padding: 18rpx 28rpx calc(18rpx + env(safe-area-inset-bottom));
		background: rgba(255, 255, 255, 0.96);
		box-shadow: 0 -8rpx 24rpx rgba(23, 54, 47, 0.06);
	}

	.submit-btn {
		height: 88rpx;
		border-radius: 46rpx;
		background: linear-gradient(135deg, #37c990, #19af7e);
		color: #fff;
		font-size: 30rpx;
		font-weight: 900;
		text-align: center;
		line-height: 88rpx;
	}

	.submit-btn.disabled {
		opacity: 0.62;
	}

	.audit-mask {
		position: fixed;
		left: 0;
		right: 0;
		top: 0;
		bottom: 0;
		z-index: 1200;
		display: flex;
		align-items: center;
		justify-content: center;
		background: rgba(12, 31, 25, 0.34);
	}

	.audit-card {
		width: 480rpx;
		padding: 48rpx 36rpx 42rpx;
		border-radius: 34rpx;
		background: rgba(255, 255, 255, 0.96);
		box-shadow: 0 24rpx 60rpx rgba(19, 70, 54, 0.18);
		text-align: center;
		box-sizing: border-box;
	}

	.audit-spinner {
		width: 124rpx;
		height: 124rpx;
		margin: 0 auto 28rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 12rpx;
		border-radius: 50%;
		background: linear-gradient(135deg, #e7fbf4, #f8fffc);
	}

	.audit-spinner view {
		width: 16rpx;
		height: 16rpx;
		border-radius: 50%;
		background: #20b985;
		animation: audit-bounce 0.9s infinite ease-in-out;
	}

	.audit-spinner view:nth-child(2) {
		animation-delay: 0.12s;
	}

	.audit-spinner view:nth-child(3) {
		animation-delay: 0.24s;
	}

	.audit-title {
		color: #17362f;
		font-size: 31rpx;
		font-weight: 900;
	}

	.audit-desc {
		margin-top: 14rpx;
		color: #84948f;
		font-size: 23rpx;
		line-height: 34rpx;
	}

	@keyframes audit-bounce {
		0%,
		80%,
		100% {
			transform: translateY(0);
			opacity: 0.45;
		}

		40% {
			transform: translateY(-18rpx);
			opacity: 1;
		}
	}

	.bottom-space {
		height: 160rpx;
	}
</style>
