<!-- 個人信息編輯頁面 -->
<template>
	<view class="pe-page">
		<view class="acct-pwd-nav" :style="{ paddingTop: statusBar + 'px' }">
			<view class="acct-pwd-nav-row">
				<view class="acct-pwd-back" @tap="goBack">
					<text class="acct-pwd-back-icon">←</text>
				</view>
				<text class="acct-pwd-nav-title">{{ copy.title }}</text>
				<view class="acct-pwd-nav-placeholder" />
			</view>
		</view>

		<scroll-view
			scroll-y
			class="acct-pwd-scroll"
			:style="{ height: scrollHeight + 'px' }"
		>
			<view class="acct-pwd-body pe-body" :style="{ paddingBottom: safeBottom + 'px' }">
				<view class="pe-card pe-avatar-card" @tap="onPickAvatar">
					<!-- #ifdef MP-WEIXIN -->
					<button
						class="pe-avatar-wx-btn"
						open-type="chooseAvatar"
						@chooseavatar="onWeixinChooseAvatar"
						@tap.stop
					/>
					<!-- #endif -->
					<view class="pe-avatar-row">
						<image
							v-if="avatarDisplay"
							class="pe-avatar-img"
							:src="avatarDisplay"
							mode="aspectFill"
						/>
						<view v-else class="pe-avatar-img pe-avatar-img--empty" />
						<view class="pe-avatar-meta">
							<text class="pe-avatar-title">{{ copy.avatar }}</text>
							<text class="pe-avatar-hint">{{ copy.changeAvatar }}</text>
						</view>
						<text class="pe-chevron">›</text>
					</view>
				</view>

				<view class="pe-card">
					<view class="pe-field">
						<text class="pe-label">{{ copy.nickname }}</text>
						<input
							v-model="form.nickname"
							class="pe-input"
							type="nickname"
							:placeholder="copy.enterNickname"
							placeholder-class="pe-placeholder"
							maxlength="32"
						/>
					</view>
					<view class="pe-field pe-field--readonly">
						<text class="pe-label">{{ copy.username }}</text>
						<text class="pe-readonly">{{ form.username || '—' }}</text>
					</view>
					<view class="pe-field">
						<text class="pe-label">{{ copy.bio }}</text>
						<input
							v-model="form.bio"
							class="pe-input"
							:placeholder="copy.enterBio"
							placeholder-class="pe-placeholder"
							maxlength="100"
						/>
					</view>
					<view class="pe-field pe-field--switch">
						<view class="pe-switch-meta">
							<text class="pe-label">{{ copy.gender }}</text>
							<text class="pe-switch-value">{{ genderLabel }}</text>
						</view>
						<switch
							:checked="genderMale"
							color="#4a8cff"
							@change="onGenderChange"
						/>
					</view>
					<view class="pe-field pe-field--last">
						<text class="pe-label">{{ copy.birthday }}</text>
						<view class="pe-picker-slot">
							<picker
								class="pe-picker"
								mode="date"
								:value="form.birthday"
								:end="todayStr"
								@change="onBirthdayChange"
							>
								<view class="pe-picker-row">
									<text class="pe-picker-value">{{ form.birthday }}</text>
									<text class="pe-chevron">›</text>
								</view>
							</picker>
						</view>
					</view>
				</view>

				<button
					class="acct-pwd-submit pe-save-btn"
					:disabled="saving"
					:loading="saving"
					:class="{ 'acct-pwd-submit--busy': saving }"
					@tap="onSave"
				>
					<text class="acct-pwd-submit__text">{{ saving ? copy.saving : copy.save }}</text>
				</button>

				<button
					class="pe-logout-btn"
					:disabled="saving"
					@tap="confirmLogout"
				>
					<text class="pe-logout-txt">{{ copy.logout }}</text>
				</button>
			</view>
		</scroll-view>

		<!-- #ifndef MP-WEIXIN -->
		<view v-if="avatarCropUrl" class="pe-crop-layer">
			<image-cutter
				:url="avatarCropUrl"
				:fixed="true"
				:width="200"
				:height="200"
				:max-width="500"
				:max-height="500"
				:blob="false"
				@ok="onAvatarCropOk"
				@cancel="onAvatarCropCancel"
			/>
		</view>
		<!-- #endif -->
	</view>
</template>

<script>
import { mapState } from 'vuex'
import { buildRestPath } from '@/core/config/api-paths'
import { post } from '@/core/http/http-client'
import {
	uploadAndUpdateAvatar,
	updateUserProfile,
	validateProfileForm,
	pickProfilePatch
} from '@/features/account/avatar-gateway'
import ImageCutter from '@/components/image-cutter/image-cutter.vue'

const DEFAULT_BIRTHDAY = '2000-01-01'

export default {
	components: { ImageCutter },
	data() {
		return {
			statusBar: 0,
			scrollHeight: 600,
			safeBottom: 0,
			saving: false,
			avatarCropUrl: '',
			avatarPreview: '',
			form: {
				nickname: '',
				username: '',
				bio: '',
				birthday: DEFAULT_BIRTHDAY,
				avatar: ''
			},
			genderMale: true
		}
	},
	computed: {
		...mapState('user', {
			storeUser: (state) => state
		}),
		copy() {
			const t = this.$t.bind(this)
			return {
				title: t('profileEdit.title'),
				avatar: t('profileEdit.avatar'),
				changeAvatar: t('profileEdit.changeAvatar'),
				nickname: t('profileEdit.nickname'),
				username: t('profileEdit.username'),
				bio: t('profileEdit.bio'),
				gender: t('profileEdit.gender'),
				birthday: t('profileEdit.birthday'),
				save: t('profileEdit.save'),
				saving: t('profileEdit.saving'),
				logout: t('profileEdit.logout'),
				enterNickname: t('profileEdit.enterNickname'),
				enterBio: t('profileEdit.enterBio'),
				male: t('profileEdit.male'),
				female: t('profileEdit.female'),
				saveOk: t('profileEdit.saveOk'),
				uploading: t('profileEdit.uploading'),
				network: t('user.realnameNetworkError'),
				logoutConfirm: t('user.panelLogoutConfirm'),
				logoutOk: t('user.panelLogoutOk'),
				prompt: t('user.panelPrompt')
			}
		},
		genderLabel() {
			return this.genderMale ? this.copy.male : this.copy.female
		},
		genderValue() {
			return this.genderMale ? 0 : 1
		},
		avatarDisplay() {
			if (this.avatarPreview) return this.avatarPreview
			const raw = this.form.avatar || this.storeUser.avatar || ''
			if (!raw) return ''
			return this.$appKit && this.$appKit.oss
				? this.$appKit.oss(raw, 192, 192, 2, 'avatar')
				: raw
		},
		todayStr() {
			const d = new Date()
			const pad = (n) => String(n).padStart(2, '0')
			return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
		}
	},
	onLoad() {
		const sys = uni.getSystemInfoSync()
		this.statusBar = sys.statusBarHeight || 0
		this.safeBottom = sys.safeAreaInsets ? sys.safeAreaInsets.bottom : 0
		const navH = this.statusBar + uni.upx2px(88)
		this.scrollHeight = (sys.windowHeight || 667) - navH
		if (!this.storeUser.isLogin) {
			uni.redirectTo({
				url: '/pages/passport/lobby',
				fail: () => uni.reLaunch({ url: '/pages/passport/lobby' })
			})
			return
		}
		this.hydrateForm()
	},
	methods: {
		goBack() {
			if (getCurrentPages().length > 1) {
				uni.navigateBack({ delta: 1 })
			} else {
				uni.switchTab({
					url: '/pages/mine/index',
					fail: () => uni.reLaunch({ url: '/pages/mine/index' })
				})
			}
		},
		hydrateForm() {
			const u = this.storeUser || {}
			this.form = {
				nickname: u.nickname || '',
				username: u.username || '',
				bio: u.bio || '',
				birthday: u.birthday || DEFAULT_BIRTHDAY,
				avatar: u.avatar || ''
			}
			this.genderMale = Number(u.gender) !== 1
		},
		onGenderChange(e) {
			this.genderMale = !!(e.detail && e.detail.value)
		},
		onBirthdayChange(e) {
			if (e.detail && e.detail.value) {
				this.form.birthday = e.detail.value
			}
		},
		onPickAvatar() {
			if (this.saving) return
			uni.chooseImage({
				count: 1,
				sizeType: ['compressed'],
				sourceType: ['album', 'camera'],
				success: (res) => {
					const path = res.tempFilePaths && res.tempFilePaths[0]
					if (path) this.avatarCropUrl = path
				}
			})
		},
		onWeixinChooseAvatar(e) {
			const path = e && e.detail && e.detail.avatarUrl
			if (path) this.uploadAvatarFile(path)
		},
		onAvatarCropCancel() {
			this.avatarCropUrl = ''
		},
		onAvatarCropOk(e) {
			this.avatarCropUrl = ''
			const path = e && e.path
			if (path) this.uploadAvatarFile(path)
		},
		async uploadAvatarFile(filePath) {
			if (!filePath || this.saving) return
			this.avatarPreview = filePath
			uni.showLoading({ mask: true, title: this.copy.uploading })
			try {
				const avatar = await uploadAndUpdateAvatar(filePath)
				this.form.avatar = avatar
				this.$store.commit('user/apply', pickProfilePatch({ avatar }))
				this.avatarPreview = ''
			} catch (err) {
				this.avatarPreview = ''
				this.$appKit.msg((err && err.message) || this.copy.network)
			} finally {
				uni.hideLoading()
			}
		},
		async onSave() {
			if (this.saving) return
			const check = validateProfileForm({
				nickname: this.form.nickname
			})
			if (!check.ok) {
				this.$appKit.msg(this.$t(check.messageKey))
				return
			}
			this.saving = true
			uni.showLoading({ mask: true })
			try {
				const payload = {
					nickname: String(this.form.nickname).trim(),
					username: this.form.username || this.storeUser.username || '',
					bio: String(this.form.bio || '').trim(),
					gender: this.genderValue,
					birthday: this.form.birthday || DEFAULT_BIRTHDAY
				}
				const updated = await updateUserProfile(payload)
				this.$store.commit('user/apply', pickProfilePatch({
					...payload,
					...updated
				}))
				this.$appKit.msg(this.copy.saveOk)
				setTimeout(() => this.goBack(), 400)
			} catch (err) {
				this.$appKit.msg((err && err.message) || this.copy.network)
			} finally {
				this.saving = false
				uni.hideLoading()
			}
		},
		confirmLogout() {
			uni.showModal({
				title: this.copy.prompt,
				content: this.copy.logoutConfirm,
				success: async (res) => {
					if (!res.confirm) return
					try {
						await post(buildRestPath('user/logout'))
					} catch (_) {}
					try {
						await this.$store.dispatch('im/pause', true)
					} catch (_) {}
					await this.$store.dispatch('clearSession')
					this.$appKit.msg(this.copy.logoutOk)
					uni.switchTab({
						url: '/pages/mine/index',
						fail: () => uni.reLaunch({ url: '/pages/mine/index' })
					})
				}
			})
		}
	}
}
</script>

<style scoped>
@import './account-flow.css';

.pe-body {
	padding-bottom: 48rpx;
}

.pe-card {
	background-color: #ffffff;
	border-radius: 24rpx;
	margin-bottom: 24rpx;
	box-shadow: 0 8rpx 32rpx rgba(26, 29, 38, 0.04);
	overflow: hidden;
}

.pe-avatar-card {
	position: relative;
	padding: 28rpx;
}

.pe-avatar-wx-btn {
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	opacity: 0;
	margin: 0;
	padding: 0;
	border: none;
	background: transparent;
}

.pe-avatar-wx-btn::after {
	border: none;
}

.pe-avatar-row {
	display: flex;
	flex-direction: row;
	align-items: center;
}

.pe-avatar-img {
	width: 120rpx;
	height: 120rpx;
	border-radius: 60rpx;
	background-color: #eef1f6;
	flex-shrink: 0;
	border: 4rpx solid #ffffff;
	box-shadow: 0 8rpx 24rpx rgba(74, 140, 255, 0.12);
}

.pe-avatar-img--empty {
	background: linear-gradient(145deg, #eef4ff 0%, #e8f0fe 100%);
}

.pe-avatar-meta {
	flex: 1;
	min-width: 0;
	margin-left: 24rpx;
}

.pe-avatar-title {
	display: block;
	font-size: 30rpx;
	font-weight: 600;
	color: #1a1d26;
}

.pe-avatar-hint {
	display: block;
	margin-top: 8rpx;
	font-size: 24rpx;
	color: #4a8cff;
}

.pe-chevron {
	font-size: 36rpx;
	color: #c5cad6;
	line-height: 1;
	flex-shrink: 0;
}

.pe-field {
	display: flex;
	flex-direction: row;
	align-items: center;
	min-height: 104rpx;
	padding: 0 28rpx;
	border-bottom: 1rpx solid #f0f2f7;
	box-sizing: border-box;
}

.pe-field--last {
	border-bottom-width: 0;
}

.pe-field--readonly {
	align-items: center;
}

.pe-field--switch {
	justify-content: space-between;
}

.pe-label {
	width: 168rpx;
	flex-shrink: 0;
	font-size: 28rpx;
	color: #1a1d26;
	font-weight: 500;
}

.pe-input {
	flex: 1;
	font-size: 28rpx;
	color: #1a1d26;
	text-align: right;
}

.pe-readonly {
	flex: 1;
	font-size: 28rpx;
	color: #8a8d9e;
	text-align: right;
}

.pe-placeholder {
	color: #b8bcc8;
}

.pe-switch-meta {
	display: flex;
	flex-direction: column;
	flex: 1;
}

.pe-switch-value {
	margin-top: 6rpx;
	font-size: 24rpx;
	color: #8a8d9e;
}

/* picker 组件不参与 flex，需外层占位与 .pe-input 一致 */
.pe-picker-slot {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: flex-end;
}

.pe-picker {
	flex: 1;
	min-width: 0;
	width: 100%;
}

.pe-picker-row {
	width: 100%;
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: flex-end;
	box-sizing: border-box;
}

.pe-picker-value {
	flex: 1;
	min-width: 0;
	font-size: 28rpx;
	color: #1a1d26;
	text-align: right;
	margin-right: 8rpx;
}

.pe-save-btn {
	margin-top: 8rpx;
}

.pe-logout-btn {
	margin-top: 20rpx;
	height: 96rpx;
	line-height: 96rpx;
	background-color: #ffffff;
	border: 2rpx solid #eef1f6;
	border-radius: 48rpx;
	box-sizing: border-box;
}

.pe-logout-btn::after {
	border: none;
}

.pe-logout-txt {
	font-size: 30rpx;
	color: #ef4444;
	font-weight: 500;
}

.pe-crop-layer {
	position: fixed;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	z-index: 10100;
}
</style>
