<template>
	<view class="detail-page">
		<!-- 顶栏 -->
		<view class="detail-nav" :style="navStyle">
			<view class="detail-nav-row">
				<view class="detail-back" @tap="goBack">
					<text class="detail-back-icon">←</text>
				</view>
				<view v-if="compactNav" class="detail-nav-user">
					<image class="detail-nav-avatar" :src="authorAvatar" mode="aspectFill" />
					<text class="detail-nav-name">{{ authorName }}</text>
				</view>
				<view v-else class="detail-nav-title">
					<text class="detail-nav-title-text">{{ copy.detailTitle }}</text>
				</view>
				<view
					v-if="post.id && !isSelfAuthor"
					class="detail-nav-report"
					hover-class="detail-nav-report--press"
					@tap="onReport"
				>
					<text class="detail-nav-report-icon">🚩</text>
				</view>
				<view v-else class="detail-nav-placeholder" />
			</view>
		</view>

		<view v-if="loading && !post.id" class="detail-state">
			<text class="detail-state-text">{{ copy.loading }}</text>
		</view>

		<view v-else-if="loadError" class="detail-state">
			<text class="detail-state-text">{{ loadError }}</text>
		</view>

		<block v-else>
			<!-- 主帖 -->
			<view id="detail-main" class="detail-main">
				<view class="detail-card">
					<view class="detail-author">
						<image class="detail-avatar" :src="authorAvatar" mode="aspectFill" />
						<view class="detail-author-meta">
							<text class="detail-nick">{{ authorName }}</text>
							<text v-if="postTime" class="detail-time">{{ postTime }}</text>
						</view>
						<view
							v-if="canFollow"
							class="detail-follow detail-follow--card"
							:class="{ 'detail-follow--on': isFollowed }"
							@tap.stop="onFollow"
						>
							<text class="detail-follow-text">{{ isFollowed ? copy.followed : copy.followPlus }}</text>
						</view>
					</view>

					<post-content-block
						ref="mainContent"
						:post="post"
						is-main
						@open-video="openVideo"
					/>

					<view class="detail-actions">
						<view class="detail-action" @tap="onLike(post)">
							<text class="detail-like" :class="{ 'detail-like--on': post.isLike === 1 }">♥</text>
							<text class="detail-action-num">{{ post.likes || 0 }}</text>
						</view>
						<view class="detail-action" @tap="openComments(post)">
							<text class="detail-comment">💬</text>
							<text class="detail-action-num">{{ post.comments || 0 }}</text>
						</view>
						<view class="detail-action">
							<text class="detail-view">👁</text>
							<text class="detail-action-num">{{ post.views || 0 }}</text>
						</view>
					</view>

					<view class="detail-comment-entry" @tap="openComments(post)">
						<image
							v-if="signedIn && userAvatar"
							class="detail-comment-avatar"
							:src="userAvatar"
							mode="aspectFill"
						/>
						<view v-else class="detail-comment-avatar detail-comment-avatar--ph" />
						<text class="detail-comment-hint">{{ copy.commentHint }}</text>
					</view>
				</view>
			</view>

			<!-- 更多推荐 -->
			<view class="detail-section-hd">
				<text class="detail-section-title">{{ copy.moreRecommend }}</text>
			</view>

			<post-card
				v-for="(item, index) in related"
				:key="item.id + '_' + index"
				:post="item"
				@open="onRelatedOpen"
				@open-detail="onRelatedOpenDetail"
				@follow="onFollowRelated"
				@like="onLike"
				@comment="openComments"
				@open-video="openVideo"
			/>

			<view class="detail-footer">
				<text class="detail-footer-text">{{ footerText }}</text>
			</view>
		</block>

		<!-- 评论弹层 -->
		<view
			v-if="commentVisible"
			class="detail-mask"
			:style="commentMaskStyle"
			@tap="closeComments"
		/>
		<view v-if="commentVisible" class="detail-sheet" :style="commentSheetStyle">
			<view class="detail-sheet-hd">
				<text class="detail-sheet-title">{{ commentSheetTitle }}</text>
				<view class="detail-sheet-close" @tap="closeComments">
					<text class="detail-sheet-close-icon">×</text>
				</view>
			</view>
			<view class="detail-sheet-body">
				<detail-comment-panel
					:find-id="commentPostId"
					:list="commentList"
					:count="commentCount"
					:safe-bottom-inset="safeBottom"
					@complete="onCommentComplete"
				/>
			</view>
		</view>
	</view>
</template>

<script>
import PostContentBlock from '@/components/dynamics/post-content-block.vue'
import PostCard from '@/components/dynamics/post-card.vue'
import DetailCommentPanel from '@/components/dynamics/detail-comment-panel.vue'
import { fetchPostDetail, fetchAuthorPosts } from '@/features/dynamics/dynamics-gateway'
import { detailPageUrl, videoDetailUrl } from '@/features/dynamics/post-media'
import {
	fetchClipComments,
	toggleClipFollow,
	toggleClipLike
} from '@/features/feed/feed-gateway'

export default {
	components: { PostContentBlock, PostCard, DetailCommentPanel },
	data() {
		return {
			postId: '',
			focusComments: false,
			post: {},
			related: [],
			loading: false,
			loadError: '',
			relatedPage: 1,
			relatedEnd: 1,
			relatedStatus: 'more',
			compactNav: false,
			mainHeight: 0,
			statusBar: 0,
			safeBottom: 0,
			windowWidth: 375,
			windowHeight: 667,
			commentVisible: false,
			commentPostId: 0,
			commentTarget: null,
			commentList: [],
			commentCount: 0
		}
	},
	computed: {
		copy() {
			const t = this.$t.bind(this)
			return {
				detailTitle: t('dynamics.detailTitle'),
				loading: t('dynamics.loading'),
				noMore: t('dynamics.noMore'),
				loadFailed: t('dynamics.loadFailed'),
				actionFailed: t('dynamics.actionFailed'),
				guest: t('dynamics.guest'),
				follow: t('dynamics.follow'),
				followPlus: t('dynamics.followPlus'),
				followed: t('dynamics.followed'),
				commentHint: t('dynamics.commentHint'),
				moreRecommend: t('dynamics.moreRecommend'),
				missingId: t('dynamics.missingId'),
				parseFailed: t('dynamics.parseFailed'),
				commentsLoadFailed: t('dynamics.commentsLoadFailed')
			}
		},
		commentSheetTitle() {
			return this.$t('dynamics.comments', { n: this.commentCount || 0 })
		},
		signedIn() {
			return !!(this.$store && this.$store.state && this.$store.state.user && this.$store.state.user.isLogin)
		},
		userAvatar() {
			const u = this.$store.state.user
			const path = (u && u.avatar) || ''
			if (this.$appKit && typeof this.$appKit.oss === 'function') {
				return this.$appKit.oss(path, 56, 56)
			}
			return path
		},
		navStyle() {
			return { paddingTop: `${this.statusBar}px` }
		},
		navHeight() {
			return this.statusBar + uni.upx2px(88)
		},
		authorName() {
			if (this.post.shop && this.post.shop.shopname) return this.post.shop.shopname
			if (this.post.user && this.post.user.nickname) return this.post.user.nickname
			return this.copy.guest
		},
		authorAvatar() {
			const path = (this.post.shop && this.post.shop.avatar)
				|| (this.post.user && this.post.user.avatar)
				|| ''
			if (this.$appKit && typeof this.$appKit.oss === 'function') {
				return this.$appKit.oss(path, 72, 72)
			}
			return path
		},
		postTime() {
			if (this.$appKit && typeof this.$appKit.timeFormat === 'function') {
				return this.$appKit.timeFormat(this.post.createtime, 'yyyy-mm-dd hh:MM') || ''
			}
			return ''
		},
		authorUserNo() {
			return this.resolveUserNo(this.post)
		},
		isSelfAuthor() {
			const u = this.$store && this.$store.state && this.$store.state.user
			if (!u || !u.isLogin) return false
			const mine = String(u.user_no || u.id || '').trim()
			const theirs = String(this.authorUserNo || '').trim()
			return !!(mine && theirs && mine === theirs)
		},
		canFollow() {
			return !!this.authorUserNo && !this.isSelfAuthor
		},
		isFollowed() {
			const flag = this.post && this.post.isFollow
			return flag === 1 || flag === '1' || flag === true
		},
		footerText() {
			if (this.relatedStatus === 'loading') return this.copy.loading
			if (this.relatedStatus === 'noMore') return this.copy.noMore
			return ''
		},
		commentSheetHeight() {
			return Math.round(this.windowHeight * 0.7)
		},
		commentSheetStyle() {
			return {
				width: `${this.windowWidth}px`,
				height: `${this.commentSheetHeight}px`
			}
		},
		commentMaskStyle() {
			return {
				width: `${this.windowWidth}px`,
				top: '0px',
				bottom: `${this.commentSheetHeight}px`
			}
		}
	},
	onLoad(query) {
		this.postId = query.id || ''
		this.focusComments = query.focus === 'comments'
		try {
			const info = uni.getSystemInfoSync()
			this.statusBar = info.statusBarHeight || 0
			this.safeBottom = (info.safeAreaInsets && info.safeAreaInsets.bottom) || 0
			this.windowWidth = info.windowWidth || 375
			this.windowHeight = info.windowHeight || 667
		} catch (_) {}
		this.bootstrap()
	},
	onPageScroll(e) {
		this.compactNav = e.scrollTop > (this.mainHeight || 320)
	},
	onReachBottom() {
		this.loadRelated()
	},
	methods: {
		goBack() {
			uni.navigateBack({
				fail: () => uni.switchTab({ url: '/pages/dynamics/index' })
			})
		},
		onReport() {
			if (!this.$appKit || !this.$appKit.requireLogin()) return
			let url = '/pages/account/complaint'
			const userNo = this.authorUserNo
			if (userNo) {
				url += `?type=0&id=${encodeURIComponent(userNo)}`
			}
			uni.navigateTo({ url })
		},
		async bootstrap() {
			if (!this.postId) {
				this.loadError = this.copy.missingId
				return
			}
			this.loading = true
			this.loadError = ''
			try {
				this.post = await fetchPostDetail(this.postId)
				if (!this.post || this.post.id == null) {
					this.loadError = this.copy.parseFailed
					return
				}
				this.related = []
				this.relatedPage = 1
				this.relatedEnd = 1
				await this.loadRelated(true)
				this.$nextTick(() => {
					setTimeout(() => this.measureMain(), 300)
				})
				if (this.focusComments) {
					this.openComments(this.post)
				}
			} catch (err) {
				this.loadError = err.message || this.copy.loadFailed
			} finally {
				this.loading = false
			}
		},
		measureMain() {
			const query = uni.createSelectorQuery().in(this)
			query.select('#detail-main').boundingClientRect((rect) => {
				if (rect && rect.height) this.mainHeight = rect.height
			}).exec()
		},
		async loadRelated(reset = false) {
			if (!this.post.user_no) return
			if (!reset && (this.relatedStatus === 'loading' || this.relatedStatus === 'noMore')) return
			if (!reset && this.relatedPage >= this.relatedEnd) {
				this.relatedStatus = 'noMore'
				return
			}
			const page = reset ? 1 : this.relatedPage + 1
			this.relatedStatus = 'loading'
			try {
				const pack = await fetchAuthorPosts(this.post.user_no, page, this.postId)
				const rows = (pack.rows || []).filter((row) => row.type !== 'activity')
				this.relatedPage = pack.currentPage || page
				this.relatedEnd = pack.lastPage || this.relatedPage
				this.related = reset ? rows : this.related.concat(rows)
				this.relatedStatus = this.relatedPage >= this.relatedEnd || !rows.length ? 'noMore' : 'more'
			} catch (_) {
				this.relatedStatus = 'noMore'
			}
		},
		async onFollow() {
			if (!this.$appKit || !this.$appKit.requireLogin()) return
			await this.toggleFollowOn(this.post)
		},
		async onFollowRelated(item) {
			if (!this.$appKit || !this.$appKit.requireLogin()) return
			await this.toggleFollowOn(item)
		},
		/** 关注接口参数：仅使用 user_no（与 setFindUser 的 id 字段一致） */
		resolveUserNo(target) {
			if (!target) return ''
			if (target.user_no != null && String(target.user_no).trim() !== '') {
				return String(target.user_no).trim()
			}
			const user = target.user
			if (user && user.user_no != null && String(user.user_no).trim() !== '') {
				return String(user.user_no).trim()
			}
			return ''
		},
		async toggleFollowOn(target) {
			const userNo = this.resolveUserNo(target)
			if (!userNo) {
				this.$appKit && this.$appKit.msg(this.copy.actionFailed)
				return
			}
			try {
				const flag = await toggleClipFollow(userNo)
				if (flag === 0 || flag === '0') {
					this.$set(target, 'isFollow', 0)
				} else if (flag === 1 || flag === '1') {
					this.$set(target, 'isFollow', 1)
				}
				if (String(target.id) === String(this.post.id)) {
					this.$set(this.post, 'isFollow', target.isFollow)
				}
				this.related.forEach((row) => {
					if (String(this.resolveUserNo(row)) === String(userNo)) {
						this.$set(row, 'isFollow', target.isFollow)
					}
				})
			} catch (err) {
				this.$appKit && this.$appKit.msg(err.message || this.copy.actionFailed)
			}
		},
		async onLike(target) {
			if (!this.$appKit || !this.$appKit.requireLogin()) return
			if (!target || !target.id) return
			try {
				const flag = await toggleClipLike(target.id)
				if (flag === 0 || flag === '0') {
					target.isLike = 0
					target.likes = Math.max(0, Number(target.likes || 0) - 1)
				} else if (flag === 1 || flag === '1') {
					target.isLike = 1
					target.likes = Number(target.likes || 0) + 1
				}
			} catch (err) {
				this.$appKit && this.$appKit.msg(err.message || this.copy.actionFailed)
			}
		},
		async openComments(target) {
			if (!target || !target.id) return
			this.commentTarget = target
			this.commentPostId = target.id
			this.commentVisible = true
			try {
				const result = await fetchClipComments(target.id)
				this.commentCount = result.count || 0
				this.commentList = Array.isArray(result.list) ? result.list : []
				target.comments = this.commentCount
			} catch (err) {
				this.commentList = []
				this.$appKit && this.$appKit.msg(err.message || this.copy.commentsLoadFailed)
			}
		},
		closeComments() {
			this.commentVisible = false
			this.commentPostId = 0
			this.commentTarget = null
			this.commentList = []
		},
		onCommentComplete(evt) {
			if (!evt || !this.commentTarget) return
			const nextCount = Number(evt.count) || 0
			this.commentTarget.comments = nextCount
			this.commentCount = nextCount
			if (Array.isArray(evt.list)) {
				this.commentList = evt.list
			}
			if (String(this.commentTarget.id) === String(this.post.id)) {
				this.post.comments = nextCount
			}
		},
		openVideo(item) {
			if (!item || !item.id) return
			uni.navigateTo({
				url: videoDetailUrl(item.id, { labelId: item.label_id })
			})
		},
		onRelatedOpen(item) {
			if (item.type === 'live' && item.live_id) {
				this.$appKit && this.$appKit.auth(`/pages/live/watch?id=${item.live_id}`)
				return
			}
			if (item.type === 'video') {
				this.openVideo(item)
				return
			}
			uni.navigateTo({ url: detailPageUrl(item.id) })
		},
		onRelatedOpenDetail(payload) {
			const id = payload && payload.id
			if (!id) return
			if (String(id) === String(this.postId)) {
				const idx = Number(payload.img) || 0
				this.$refs.mainContent && this.$refs.mainContent.previewImages(idx)
				uni.pageScrollTo({ scrollTop: 0, duration: 200 })
				return
			}
			uni.navigateTo({
				url: detailPageUrl(id, { img: payload.img })
			})
		}
	}
}
</script>

<style scoped>
.detail-page {
	min-height: 100vh;
	background-color: #eef3fb;
	padding-bottom: 40rpx;
}
.detail-nav {
	position: sticky;
	top: 0;
	z-index: 20;
	background-color: rgba(238, 243, 251, 0.96);
	backdrop-filter: blur(8px);
}
.detail-nav-row {
	display: flex;
	flex-direction: row;
	align-items: center;
	height: 88rpx;
	padding: 0 24rpx;
}
.detail-back {
	width: 64rpx;
	height: 64rpx;
	border-radius: 18rpx;
	background-color: #ffffff;
	box-shadow: 0 4rpx 16rpx rgba(74, 140, 255, 0.1);
	display: flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
.detail-back-icon {
	font-size: 34rpx;
	color: #4a8cff;
}
.detail-nav-title {
	flex: 1;
	margin-left: 16rpx;
}
.detail-nav-title-text {
	font-size: 32rpx;
	font-weight: 700;
	color: #4a8cff;
}
.detail-nav-user {
	flex: 1;
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-left: 16rpx;
	min-width: 0;
}
.detail-nav-avatar {
	width: 56rpx;
	height: 56rpx;
	border-radius: 28rpx;
	background-color: #eef2f8;
	flex-shrink: 0;
}
.detail-nav-name {
	margin-left: 12rpx;
	font-size: 28rpx;
	font-weight: 600;
	color: #1a1d26;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.detail-nav-placeholder,
.detail-nav-report {
	width: 64rpx;
	flex-shrink: 0;
}
.detail-follow {
	height: 56rpx;
	border-radius: 999rpx;
	background-color: #4a8cff;
	display: flex;
	align-items: center;
	justify-content: center;
}
.detail-nav-report {
	height: 64rpx;
	border-radius: 18rpx;
	background-color: #ffffff;
	box-shadow: 0 4rpx 16rpx rgba(74, 140, 255, 0.1);
	display: flex;
	align-items: center;
	justify-content: center;
}
.detail-nav-report--press {
	opacity: 0.82;
}
.detail-nav-report-icon {
	font-size: 30rpx;
	line-height: 1;
}
.detail-follow--on {
	background-color: #ffffff;
	border: 1rpx solid rgba(74, 140, 255, 0.25);
}
.detail-follow-text {
	font-size: 24rpx;
	color: #ffffff;
	font-weight: 600;
}
.detail-follow--on .detail-follow-text {
	color: #4a8cff;
}
.detail-state {
	padding: 120rpx 0;
	text-align: center;
}
.detail-state-text {
	font-size: 28rpx;
	color: #8a8d9e;
}
.detail-main {
	padding-top: 12rpx;
}
.detail-card {
	margin: 0 32rpx 28rpx;
	padding: 28rpx;
	background-color: #ffffff;
	border-radius: 28rpx;
	box-shadow: 0 8rpx 32rpx rgba(74, 140, 255, 0.08);
}
.detail-author {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-bottom: 24rpx;
}
.detail-follow--card {
	width: auto;
	min-width: 112rpx;
	padding: 0 20rpx;
	margin-left: 12rpx;
}
.detail-avatar {
	width: 80rpx;
	height: 80rpx;
	border-radius: 40rpx;
	background-color: #eef2f8;
	flex-shrink: 0;
}
.detail-author-meta {
	margin-left: 20rpx;
	flex: 1;
	min-width: 0;
}
.detail-nick {
	font-size: 32rpx;
	font-weight: 700;
	color: #1a1d26;
	display: block;
}
.detail-time {
	font-size: 24rpx;
	color: #8a8d9e;
	margin-top: 6rpx;
}
.detail-actions {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-top: 28rpx;
	padding-top: 24rpx;
	border-top: 1rpx solid rgba(0, 0, 0, 0.05);
}
.detail-action {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-right: 40rpx;
}
.detail-like,
.detail-comment,
.detail-view {
	font-size: 32rpx;
	margin-right: 8rpx;
	color: #b0b4c0;
}
.detail-like--on {
	color: #ff4d4f;
}
.detail-action-num {
	font-size: 26rpx;
	color: #5c6070;
}
.detail-comment-entry {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-top: 24rpx;
	padding: 16rpx 20rpx;
	border-radius: 999rpx;
	background-color: #f5f7fb;
}
.detail-comment-avatar {
	width: 56rpx;
	height: 56rpx;
	border-radius: 28rpx;
	background-color: #eef2f8;
	flex-shrink: 0;
}
.detail-comment-avatar--ph {
	background-color: #dce6f5;
}
.detail-comment-hint {
	margin-left: 16rpx;
	font-size: 26rpx;
	color: #8a8d9e;
}
.detail-section-hd {
	padding: 8rpx 32rpx 20rpx;
}
.detail-section-title {
	font-size: 34rpx;
	font-weight: 700;
	color: #1a1d26;
}
.detail-footer {
	padding: 12rpx 0 32rpx;
	text-align: center;
}
.detail-footer-text {
	font-size: 24rpx;
	color: #b0b4c0;
}
.detail-mask {
	position: fixed;
	left: 0;
	right: 0;
	z-index: 30;
	background-color: rgba(0, 0, 0, 0.45);
}
.detail-sheet {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 31;
	background-color: #ffffff;
	border-radius: 24rpx 24rpx 0 0;
	overflow: hidden;
	display: flex;
	flex-direction: column;
}
.detail-sheet-body {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
}
.detail-sheet-hd {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	height: 88rpx;
	padding: 0 32rpx;
	border-bottom: 1rpx solid rgba(0, 0, 0, 0.06);
}
.detail-sheet-title {
	font-size: 30rpx;
	font-weight: 700;
	color: #1a1d26;
}
.detail-sheet-close {
	width: 56rpx;
	height: 56rpx;
	display: flex;
	align-items: center;
	justify-content: center;
}
.detail-sheet-close-icon {
	font-size: 40rpx;
	color: #8a8d9e;
	line-height: 1;
}
</style>
