<template>
	<view class="work-container">
		<site-switch-header :site-id="siteId" :site-type-options="siteTypeOptions" :site-address="baseInfo.siteAddress"
			:running-time="baseInfo.runningTime" :site-count="siteCount" @change="selectedSite" />
		<!-- 静态信息 -->
		<view class="base-info">
			<uni-group mode="card" class="install-data">
				<uni-grid :column="2" :showBorder="false" :square="false" :highlight="false">
					<uni-grid-item>
						<view class="grid-item-box">
							<view class="title">装机功率(MWh)</view>
							<view class="text">{{baseInfo.installPower | formatNumber}}</view>
						</view>
					</uni-grid-item>
					<uni-grid-item>
						<view class="grid-item-box">
							<view class="title">装机容量(MWh)</view>
							<view class="text">{{baseInfo.installCapacity | formatNumber}}</view>
						</view>
					</uni-grid-item>
				</uni-grid>
			</uni-group>
			<!-- 工作台 -->
			<uni-section title="工作台" type="line" class="sections-list">
				<view class="grid-body">
					<uni-grid :column="4" :showBorder="false" @change="toDetail">
						<uni-grid-item v-for="(item,index) in siteGirdList" :index="index" :key="index+'work'">
							<view class="grid-item-box work-box">
								<image v-if="item.image" :src="item.image" class="icon icon-image" mode="aspectFit" />
								<view v-else class="icon iconfont" :class="item.icon" size="30"></view>
								<text class="text">{{item.text}}</text>
							</view>
						</uni-grid-item>
					</uni-grid>
				</view>
			</uni-section>
			<!-- 一周充放曲线 uchart的组件最好放在同级-->
			<uni-section title="一周充放曲线" type="line" class="sections-list">
				<date-range-select ref="weekChartDateRangeSelect" @updateDate="updateWeekChartDate" />
				<view style="width:100%;height: 250px;">
					<qiun-data-charts type="area" :chartData="weekChartData" :optsWatch='false' :inScrollView="true"
						:pageScrollTop="pageScrollTop" :opts="options" :ontouch="true" />
				</view>
			</uni-section>
			<!-- 当日功率曲线 uchart的组件最好放在同级-->
			<uni-section title="当日功率曲线" type="line" class="sections-list">
				<date-range-select ref="activeChartDateRangeSelect" @updateDate="updateActiveChartDate" />
				<view style="width:100%;height: 250px;">
					<qiun-data-charts type="area" :chartData="activeChartData" :optsWatch='false' :inScrollView="true"
						:pageScrollTop="pageScrollTop" :opts="glqxOptions" :ontouch="true" />
				</view>
			</uni-section>
		</view>
	</view>
</template>

<script>
	import {
		mapGetters
	} from 'vuex'
	import DateRangeSelect from './DateRangeSelect.vue'
	import SiteSwitchHeader from '@/components/SiteSwitchHeader/index.vue'
	import {
		getAllSites,
		getSingleSiteBaseInfo,
		getProjectDisplayData,
		getPointConfigCurve,
		getSiteAllDeviceCategory
	} from '@/api/ems/site.js'
	const createSiteTypeOptions = () => ([{
			text: '储能',
			value: 'cn',
			children: []
		},
		{
			text: '光能',
			value: 'gn',
			children: []
		},
		{
			text: '岸电',
			value: 'ad',
			children: []
		}
	])
	export default {
		components: {
			DateRangeSelect,
			SiteSwitchHeader
		},
		data() {
			return {
				// 图表数据
				weekChartTimeRange: [],
				activeChartTimeRange: [],
				weekChartData: {},
				activeChartData: {},
				curveDisplayData: [],
				curveDisplayLoadingPromise: null,
				pageScrollTop: 0,
				glqxOptions: {
					padding: [10, 5, 0, 10],
					dataLabel: false,
					enableScroll: true,
					xAxis: {
						scrollShow: true,
						itemCount: 3,
						disableGrid: true
					},
					extra: {
						area: {
							type: "curve",
							opacity: 0.2,
							addLine: true,
							width: 2,
							gradient: true,
							activeType: "hollow"
						}
					}
					// update: true,
					// duration: 2,
					// animation: false,
					// enableScroll: true,
					// padding: [10, 15, 10, 15]
				},
				options: {
					padding: [10, 5, 0, 10],
					dataLabel: false,
					enableScroll: true,
					xAxis: {
						scrollShow: true,
						itemCount: 5,
						disableGrid: true
					},
					extra: {
						area: {
							type: "curve",
							opacity: 0.2,
							addLine: true,
							width: 2,
							gradient: true,
							activeType: "hollow"
						}
					}
					// update: true,
					// duration: 2,
					// animation: false,
					// enableScroll: true,
					// padding: [10, 15, 10, 15]
				},
				// 图表数据结束
				deviceCategoryOptions: [], //当前站点包含的设备类别
				siteTypeOptions: createSiteTypeOptions(),
				siteId: '', //选择的站点ID
				baseInfo: {}, //站点基本信息
				gridList: [{
						page: 'bmszl',
						icon: 'icon-BMS',
						text: 'BMS总览',
						categoryName: 'STACK'
					},
					{
						page: 'bmsdcc',
						icon: 'icon-a-dianchicunengliangkuai',
						text: 'BMS电池簇',
						categoryName: 'CLUSTER'
					},
					{
						page: 'pcs',
						icon: 'icon-PCS',
						text: 'PCS',
						categoryName: 'PCS'
					},
					{
						page: 'db',
						icon: 'icon-dianbiao4',
						text: '电表',
						categoryName: 'AMMETER'
					},
					{
						page: 'yl',
						icon: 'icon-gongneng-diandongji',
						text: '冷却',
						categoryName: 'COOLING'
					},
					{
						page: 'dtdc',
						icon: 'icon-dantidianchi',
						text: '单体电池',
						categoryName: 'BATTERY'
					},
					{
						page: 'report',
						icon: 'icon-service',
						image: '/static/images/work/report.svg',
						text: '报表',
						categoryName: ''
					}
				]
			}
		},
		computed: {
			...mapGetters(['belongSite', 'currentSiteId']),
			siteCount() {
				return (this.siteTypeOptions || []).reduce((count, typeItem) => {
					return count + ((typeItem.children || []).length)
				}, 0)
			},
			siteGirdList() {
				return this.gridList.filter(i => !i.categoryName || this.deviceCategoryOptions.includes(i.categoryName))
			}
		},
		methods: {
			isAvailableSite(siteId) {
				const allSites = this.siteTypeOptions.reduce((result, typeItem) => {
					return result.concat(typeItem.children || [])
				}, [])
				const site = allSites.find(item => item.value === siteId)
				return !!(site && !site.disable)
			},
			// 更新一周冲放曲线时间范围 重置图表
			updateWeekChartDate(data) {
				this.weekChartTimeRange = data || []
				this.siteId && this.getWeekChartData()
			},
			// 更新当日功率曲线时间范围 重置图表
			updateActiveChartDate(data) {
				this.activeChartTimeRange = data || []
				this.siteId && this.getGVQXData()
			},
			toDetail(e) {
				if (!this.siteId) return uni.showToast({
					title: "请选择清单",
					icon: 'none'
				})
				const {
					index
				} = e.detail
				this.$tab.navigateTo(`/pages/work/${this.siteGirdList[index].page}/index?siteId=${this.siteId}`)
			},
			selectedSite(data) {
				const siteObj = (data.detail.value || [])[1]
				const value = siteObj?.value
				if (!value) return
				if (value === this.siteId) return
				this.siteId = value
				this.$store.commit('SET_CURRENTSITEID', value)
				this.updateSiteInfo()
			},
			updateSiteInfo() {
				if (!this.siteId) return
				this.curveDisplayData = []
				this.curveDisplayLoadingPromise = null
				this.getSiteBaseInfo()
				this.getWeekChartData()
				this.getGVQXData()
				this.getSiteDeviceCategory()
			},
			getFieldName(fieldCode) {
				const raw = String(fieldCode || '').trim()
				if (!raw) return ''
				const index = raw.lastIndexOf('__')
				return index >= 0 ? raw.slice(index + 2) : raw
			},
			normalizeDateTime(value, endOfDay) {
				const raw = String(value || '').trim()
				if (!raw) return ''
				if (raw.includes(' ')) return raw
				return `${raw} ${endOfDay ? '23:59:59' : '00:00:00'}`
			},
			parseToTimestamp(value) {
				if (!value) return null
				const timestamp = new Date(value).getTime()
				return Number.isNaN(timestamp) ? null : timestamp
			},
			ensureCurveDisplayData() {
				if (!this.siteId) return Promise.resolve([])
				if (this.curveDisplayData.length > 0) return Promise.resolve(this.curveDisplayData)
				if (this.curveDisplayLoadingPromise) return this.curveDisplayLoadingPromise
				this.curveDisplayLoadingPromise = getProjectDisplayData(this.siteId)
					.then(response => {
						this.curveDisplayData = response?.data || []
						return this.curveDisplayData
					})
					.catch(() => {
						this.curveDisplayData = []
						return []
					})
					.finally(() => {
						this.curveDisplayLoadingPromise = null
					})
				return this.curveDisplayLoadingPromise
			},
			fetchCurveSeries(pointId, name, startTime, endTime) {
				if (!pointId) return Promise.resolve(null)
				return getPointConfigCurve({
					siteId: this.siteId,
					pointId,
					pointType: 'data',
					rangeType: 'custom',
					startTime,
					endTime
				}).then(response => {
					const list = response?.data || []
					const points = list.map(item => {
						const timestamp = this.parseToTimestamp(item.dataTime)
						const value = Number(item.pointValue)
						if (!timestamp || Number.isNaN(value)) return null
						return {
							timestamp,
							label: item.dataTime,
							value
						}
					}).filter(Boolean)
					return {
						name,
						points
					}
				}).catch(() => null)
			},
			buildLineChartData(seriesList) {
				const validSeries = (seriesList || []).filter(item => item && (item.points || []).length > 0)
				if (validSeries.length === 0) {
					return {
						categories: [],
						series: []
					}
				}
				const labelByTimestamp = {}
				const timestampSet = new Set()
				validSeries.forEach(item => {
					item.points.forEach(point => {
						timestampSet.add(point.timestamp)
						if (!labelByTimestamp[point.timestamp]) {
							labelByTimestamp[point.timestamp] = point.label
						}
					})
				})
				const sortedTimestamps = Array.from(timestampSet).sort((a, b) => a - b)
				const categories = sortedTimestamps.map(item => labelByTimestamp[item])
				const series = validSeries.map(item => {
					const pointMap = {}
					item.points.forEach(point => {
						pointMap[point.timestamp] = point.value
					})
					return {
						name: item.name,
						data: sortedTimestamps.map(timestamp => pointMap[timestamp] ?? null)
					}
				})
				return {
					categories,
					series
				}
			},
			findActiveCurveRow(sectionRows, keywords = []) {
				const keywordSet = new Set((keywords || []).map(item => String(item || '').toLowerCase()))
				return (sectionRows || []).find(row => {
					const fieldCode = this.getFieldName(row?.fieldCode).toLowerCase()
					const fieldName = String(row?.fieldName || '').toLowerCase()
					if (keywordSet.has(fieldCode) || keywordSet.has(fieldName)) return true
					return Array.from(keywordSet).some(keyword => fieldCode.includes(keyword) || fieldName.includes(keyword))
				})
			},
			getSiteList() {
				getAllSites().then(response => {
					const data = response?.data || []
					const canAccessAll = !this.belongSite || this.belongSite.length === 0 || this.belongSite.includes('all')
					const siteTypeOptions = createSiteTypeOptions().map(item => ({
						...item,
						children: []
					}))
					data.forEach(item => {
						if (!canAccessAll && !this.belongSite.includes(item.siteId)) return
						const siteType = (item.siteType || item.type || 'cn').toString().toLowerCase()
						const typeOption = siteTypeOptions.find(i => i.value === siteType) || siteTypeOptions.find(i => i.value === 'cn')
						if (!typeOption) return
						typeOption.children.push({
							text: item.siteName,
							value: item.siteId,
							id: item.id
						})
					})
					this.siteTypeOptions = siteTypeOptions.filter(item => (item.children || []).length > 0)
					const siteChildren = this.siteTypeOptions.reduce((result, typeItem) => {
						return result.concat(typeItem.children || [])
					}, [])
					// 设置默认展示的站点
					const defaultSiteId = this.isAvailableSite(this.currentSiteId) ? this.currentSiteId : (siteChildren[0]?.value || '')
					if (defaultSiteId) {
						this.siteId = defaultSiteId
						this.$store.commit('SET_CURRENTSITEID', defaultSiteId)
						this.updateSiteInfo()
					}
				})
			},
			getSiteBaseInfo() {
				getSingleSiteBaseInfo({
					siteId: this.siteId
				}).then(response => {
					console.log('获取站点基本信息', response)
					this.baseInfo = response?.data || {}
				})
			},
			getSiteDeviceCategory() {
				getSiteAllDeviceCategory({
					siteId: this.siteId
				}).then(response => {
					this.deviceCategoryOptions = response?.data || []
				})
			},
			handleDate(date) {
				if (!date) return date
				const time = new Date(date)
				const month = time.getMonth() + 1,
					day = time.getDate()
				return `${month<10?'0'+month : month}/${day<10 ? '0'+day : day}`
			},
			getGVQXData() {
				this.$refs.activeChartDateRangeSelect.showBtnLoading(true)
				const startTime = this.normalizeDateTime(this.activeChartTimeRange[0], false)
				const endTime = this.normalizeDateTime(this.activeChartTimeRange[1], true)
				this.ensureCurveDisplayData().then(displayData => {
					const sectionRows = (displayData || []).filter(item =>
						item && item.sectionName === '当日功率曲线' && item.useFixedDisplay !== 1 && item.dataPoint
					)
					const targetRows = [{
							name: '电网功率',
							row: this.findActiveCurveRow(sectionRows, ['gridpower', '电网功率'])
						},
						{
							name: '负载功率',
							row: this.findActiveCurveRow(sectionRows, ['loadpower', '负载功率'])
						},
						{
							name: '储能功率',
							row: this.findActiveCurveRow(sectionRows, ['storagepower', '储能功率'])
						}
					].filter(item => item.row && item.row.dataPoint)
					const tasks = targetRows.map(item => this.fetchCurveSeries(String(item.row.dataPoint).trim(), item.name, startTime,
						endTime))
					return Promise.all(tasks).then(series => {
						this.activeChartData = JSON.parse(JSON.stringify(this.buildLineChartData((series || []).filter(Boolean))))
					})
				}).finally(() => this.$refs.activeChartDateRangeSelect.showBtnLoading(false))

			},
			getWeekChartData() {
				this.$refs.weekChartDateRangeSelect.showBtnLoading(true)
				const startTime = this.normalizeDateTime(this.weekChartTimeRange[0], false)
				const endTime = this.normalizeDateTime(this.weekChartTimeRange[1], true)
				this.ensureCurveDisplayData().then(displayData => {
					const sectionRows = (displayData || []).filter(item =>
						item && item.sectionName === '一周充放曲线' && item.useFixedDisplay !== 1 && item.dataPoint
					)
					const tasks = sectionRows.map(row => {
						const pointId = String(row.dataPoint || '').trim()
						if (!pointId) return Promise.resolve(null)
						const name = row.fieldName || this.getFieldName(row.fieldCode) || pointId
						return this.fetchCurveSeries(pointId, name, startTime, endTime)
					})
					return Promise.all(tasks).then(series => {
						this.weekChartData = JSON.parse(JSON.stringify(this.buildLineChartData((series || []).filter(Boolean))))
					})
				}).finally(() => this.$refs.weekChartDateRangeSelect.showBtnLoading(false))
			}
		},
		watch: {
			currentSiteId(newSiteId) {
				if (!newSiteId || newSiteId === this.siteId) return
				if (!this.isAvailableSite(newSiteId)) return
				this.siteId = newSiteId
				this.updateSiteInfo()
			}
		},
		// 页面切换不会重新调用，如果希望每次切换页面都重新调接口，使用onShow
		onLoad() {
			this.$nextTick(() => {
				this.getSiteList()
				this.$refs.weekChartDateRangeSelect.init()
				this.$refs.activeChartDateRangeSelect.init(true)
			})
		},
		// 页面滚动 设置pageScrollTop chart显示需要
		onPageScroll(e) {
			this.pageScrollTop = e.scrollTop
		},
	}
</script>

<style lang="scss" scoped>
	/* #ifndef APP-NVUE */
	page {
		display: flex;
		flex-direction: column;
		box-sizing: border-box;
		background-color: #fff;
		min-height: 100%;
		height: auto;
		font-size: 26rpx;
		line-height: 30rpx;
	}

	view {
		line-height: inherit;
	}

	/* #endif */

	.text {
		text-align: center;
		margin-top: 10rpx;
	}

	// 基本信息
	.base-info {
		margin-top: -80rpx;
		border-radius: 80rpx 80rpx 0 0;
		padding: 30rpx;
		background-color: #fff;

		// 装机功率
		.install-data {
			.grid-item-box {
				padding-top: 6rpx;
				padding-bottom: 6rpx;

				.text {
					margin-top: 20rpx;
					color: #000;
				}
			}

		}


		.sections-list {
			margin-bottom: 10rpx;

			::v-deep &>.uni-section-header {
				font-weight: 700;
				font-size: 26rpx;
				line-height: 30rpx;
			}
		}

		.sections-list:not(:first-child) {
			margin-top: 40rpx;
		}

		::v-deep {
			.uni-section__content-title {
				font-size: 26rpx !important;
			}

			.uni-select__input-box {
				width: 100%;

				.uni-select__input-text {
					font-size: 24rpx;
				}
			}

			.uni-select__selector-empty,
			.uni-select__selector-item {
				font-size: 24rpx;
				line-height: 36rpx;
				padding-top: 10rpx;
				padding-bottom: 10rpx;
				text-align: left;
			}

			// .uni-date__x-input {
			// 	height: 50rpx;
			// 	line-height: 50rpx;
			// 	font-size: 26rpx;
			// }
		}

		.work-box {

			.icon {
				font-size: 52rpx;
				color: #547ef4;
			}

			.icon-image {
				width: 56rpx;
				height: 56rpx;
				display: block;
				margin: 0 auto;
			}

			.text {
				font-size: 26rpx;
				padding-top: 10rpx;
				color: #000;
			}
		}

		.base-lists {
			font-size: 24rpx;
			line-height: 40rpx;
			padding: 10rpx 20rpx;
			padding-left: 40rpx;

			.left {
				width: 220rpx;
				display: inline-block;
				color: #666;
			}

			.right {
				color: #333;
			}
		}
	}

	@media screen and (min-width: 500px) {}
</style>
