<template>
	<view class="default_page" :style="{'height':h+'px', 'padding-top':mt+'px'}">
		<cus-header title='生成报告' bgColor="transparent"></cus-header>
		<div class="box adffcac">
			<image class="box-loading" src="https://gitee.com/hw_0302/chuang-heng-wechat-images/raw/e6d5bea9491a14aafd3f955d332e62d08e521229/report_success.png" v-if="generation.imageKey==='success'"></image>
			<image class="box-loading" src="https://gitee.com/hw_0302/chuang-heng-wechat-images/raw/e6d5bea9491a14aafd3f955d332e62d08e521229/report_fail.png" v-else></image>
			<div class="box-p1">{{generation.title}}</div>
			<div class="box-p2" v-if="generation.subtitle">{{generation.subtitle}}</div>
			<div class="box-p3">{{generation.state===-1 ? '失败原因：'+generation.errorMessage : generation.description}}</div>
		</div>
		<div class="form">
			<div class="form-item adfacjb">
				<div class="form-item-left">问卷名称</div>
				<div class="form-item-right">{{info.title||''}}</div>
			</div>
			<div class="form-item adfacjb">
				<div class="form-item-left">团队名称</div>
				<div class="form-item-right">{{info.teamName||''}}</div>
			</div>
			<div class="form-item adfacjb">
				<div class="form-item-left">创建时间</div>
				<div class="form-item-right">{{info.startTime||info.createDate||''}}</div>
			</div>
		</div>
		<div class="btn">
			<div class="zt_btn" @click="handleAction">{{generation.actionText}}</div>
		</div>
	</view>
</template>

<script>
	function toNumber(value) {
		if (value === '' || value === null || value === undefined) return undefined
		const numeric = Number(value)
		return Number.isNaN(numeric) ? undefined : numeric
	}

	function extractReportId(payload) {
		if (payload === null || payload === undefined) return undefined
		if (typeof payload === 'number') return payload
		if (typeof payload === 'string') return toNumber(payload)
		if (typeof payload !== 'object') return undefined
		const direct = toNumber(payload.reportId ?? payload.id)
		if (direct !== undefined) return direct
		for (const key of ['data', 'dto', 'info']) {
			const nested = extractReportId(payload[key])
			if (nested !== undefined) return nested
		}
		return undefined
	}

	function normalizeGenerationStatus(payload = {}) {
		const source = payload && typeof payload === 'object' ? payload : {}
		const state = toNumber(source.state)
		return {
			reportId: extractReportId(source) || '',
			state: state === undefined ? 0 : state,
			status: source.status || '',
			errorMessage: source.errorMessage || ''
		}
	}

	function applyGenerationStatus(payload = {}) {
		const generation = normalizeGenerationStatus(payload)
		if (generation.state === -1) {
			return {
				...generation,
				title: '报告生成失败',
				subtitle: '',
				description: generation.errorMessage || '失败原因：网络延迟',
				errorMessage: generation.errorMessage || '网络延迟',
				polling: false,
				actionText: '重新生成',
				imageKey: 'fail'
			}
		}
		if (generation.state === 1) {
			return {
				...generation,
				title: '报告生成成功',
				subtitle: '',
				description: '报告已生成完成，你可以去我的PREILL报告查阅报告结果。',
				errorMessage: '',
				polling: false,
				actionText: '返回',
				imageKey: 'success'
			}
		}
		return {
			...generation,
			title: '报告正在生成中~',
			subtitle: '预计所需时间1小时左右',
			description: '我们会在报告生成完成后提示你，你可以去我的PREILL报告查阅报告结果。',
			errorMessage: '',
			polling: true,
			actionText: '返回',
			imageKey: 'success'
		}
	}

	function shouldResumePolling(reportId, generation = {}) {
		return Boolean(reportId && normalizeGenerationStatus(generation).state === 0)
	}

	function setStatusPageVisible(vm, visible) {
		if(vm.isPageVisible === visible) return vm.statusVisibilityToken
		vm.isPageVisible = visible
		if(!visible){
			vm.statusVisibilityToken++
			vm.statusActiveRequestId = 0
			vm.statusRequestInFlight = false
		}
		return vm.statusVisibilityToken
	}

	function beginStatusRequest(vm) {
		if(!vm.isPageVisible || vm.statusRequestInFlight) return null
		vm.statusRequestSeq++
		vm.statusActiveRequestId = vm.statusRequestSeq
		vm.statusRequestInFlight = true
		return {
			requestId: vm.statusActiveRequestId,
			visibilityToken: vm.statusVisibilityToken
		}
	}

	function shouldApplyStatusResponse(vm, meta) {
		return Boolean(
			meta
			&& vm.isPageVisible
			&& vm.statusRequestInFlight
			&& vm.statusActiveRequestId === meta.requestId
			&& vm.statusVisibilityToken === meta.visibilityToken
		)
	}

	function finishStatusRequest(vm, meta) {
		if(!meta) return
		if(vm.statusActiveRequestId === meta.requestId){
			vm.statusActiveRequestId = 0
			vm.statusRequestInFlight = false
		}
	}

	export default {
		data(){
			return {
				reportId:'',
				info:{},
				generation:applyGenerationStatus(),
				pollTimer:null,
				hasStatusErrorToastShown:false,
				isPageVisible:false,
				statusVisibilityToken:0,
				statusRequestSeq:0,
				statusActiveRequestId:0,
				statusRequestInFlight:false
			}
		},
		onLoad(options) {
			this.info = options.info&&JSON.parse(decodeURIComponent(options.info)) || {}
			this.reportId = extractReportId({ reportId:options.reportId, dto:options, info:this.info }) || ''
			if(!this.reportId){
				this.stopPolling('报告编号缺失')
				return
			}
		},
		onShow() {
			setStatusPageVisible(this, true)
			if(shouldResumePolling(this.reportId, this.generation)){
				this.startPolling()
				this.fetchGenerationStatus(false)
			}
		},
		onHide() {
			setStatusPageVisible(this, false)
			this.clearPolling()
		},
		onUnload() {
			setStatusPageVisible(this, false)
			this.clearPolling()
		},
		methods:{
			startPolling(){
				if(!this.isPageVisible || !shouldResumePolling(this.reportId, this.generation) || this.pollTimer) return
				this.pollTimer = setInterval(() => {
					this.fetchGenerationStatus(false)
				}, 5000)
			},
			clearPolling(){
				if(this.pollTimer){
					clearInterval(this.pollTimer)
					this.pollTimer = null
				}
			},
			reconcileGeneration(status){
				this.generation = applyGenerationStatus(status)
				this.hasStatusErrorToastShown = false
				if(this.generation.polling && this.reportId) return this.startPolling()
				this.clearPolling()
			},
			stopPolling(errorMessage){
				this.clearPolling()
				this.generation = applyGenerationStatus({
					reportId:this.reportId,
					state:-1,
					errorMessage:errorMessage || this.generation.errorMessage || '网络延迟'
				})
			},
			fetchGenerationStatus(showErrorToast = true){
				if(!this.reportId){
					this.stopPolling('报告编号缺失')
					return Promise.resolve()
				}
				const requestMeta = beginStatusRequest(this)
				if(!requestMeta) return Promise.resolve()
				return this.$api.get(`/core/report/generationStatus/${this.reportId}`, {}, false).then(({data:res})=>{
					if(!shouldApplyStatusResponse(this, requestMeta)) return
					if(res.code!==0){
						if(showErrorToast && !this.hasStatusErrorToastShown){
							this.$showToast(res.msg || '报告状态获取失败')
							this.hasStatusErrorToastShown = true
						}
						this.startPolling()
						return
					}
					this.reconcileGeneration({ ...(res.data || {}), reportId:this.reportId })
				}).catch(error => {
					if(!shouldApplyStatusResponse(this, requestMeta)) return
					const message = error && (error.message || error.msg) || '报告状态获取失败'
					if(showErrorToast && !this.hasStatusErrorToastShown){
						this.$showToast(message)
						this.hasStatusErrorToastShown = true
					}
					this.startPolling()
				}).finally(() => {
					finishStatusRequest(this, requestMeta)
				})
			},
			handleAction(){
				if(this.generation.state===-1){
					this.handleReCreate()
					return
				}
				uni.navigateBack()
			},
			handleReCreate(){
				this.$api.get(`/core/team/questionnaire/genReport/${this.info.teamQuestionnaireId}`).then(({data:res})=>{
					if(res.code!==0) return this.$showToast(res.msg)
					const nextReportId = extractReportId(res.data)
					if(!nextReportId) return this.$showToast('未获取到报告编号')
					this.$showToast('重新生成成功')
					uni.redirectTo({
						url:'/pagesHome/reportResult?reportId='+nextReportId+'&info='+encodeURIComponent(JSON.stringify(this.info))
					})
				})
			}
		}
	}
</script>

<style scoped lang="scss">
	.default_page{
		background: #F7F7F7;
		.box{
			width: 100%;
			background: #FFFFFF;
			border-radius: 36rpx 36rpx 0rpx 0rpx;
			padding: 54rpx 0 64rpx;
			&-loading{
				width: 340rpx;
				height: 340rpx;
			}
			&-p1{
				font-family: PingFang-SC, PingFang-SC;
				font-weight: bold;
				font-size: 32rpx;
				color: #002846;
				line-height: 40rpx;
				text-align: center;
				margin-top: 41rpx;
			}
			&-p2{
				font-family: PingFang-SC, PingFang-SC;
				font-weight: bold;
				font-size: 28rpx;
				color: #002846;
				line-height: 28rpx;
				text-align: center;
				margin-top: 23rpx;
			}
			&-p3{
				padding: 0 100rpx;
				font-family: PingFangSC, PingFang SC;
				font-weight: 400;
				font-size: 28rpx;
				color: #667E90;
				line-height: 42rpx;
				text-align: center;
				margin-top: 24rpx;
			}
		}
		
		.form{
			width: 100%;
			margin-top: 20rpx;
			&-item{
				padding: 28rpx 24rpx;
				background: #FFFFFF;
				box-shadow: inset 0rpx -1rpx 0rpx 0rpx #EFEFEF;
				&-left{
					width: 140rpx;
					font-family: PingFangSC, PingFang SC;
					font-weight: 400;
					font-size: 30rpx;
					color: #002846;
					line-height: 42rpx;
				}
				&-right{
					width: calc(100% - 140rpx);
					padding-left: 20rpx;
					box-sizing: border-box;
					font-family: PingFangSC, PingFang SC;
					font-weight: 400;
					font-size: 30rpx;
					color: #667E90;
					line-height: 32rpx;
					text-align: right;
				}
			}
		}
		
		.btn{
			width: calc(100% -100rpx);
			margin: 120rpx 50rpx 0;
		}
	}
</style>
