<script setup lang="ts">
import {ref, reactive, computed, onMounted, nextTick} from 'vue'
import {
	Storehouse_StockOut_Company_Name_List,
	Storehouse_Company_Device_Statistics,
	Storehouse_Company_Device_Statistics_Excel
} from '@/api/storehouse'
import {useTablePublic} from '@/hooks/useTablePublic'
import {ElMessage} from 'element-plus'

// 左侧公司列表搜索与滚动
const {globalStore} = useTablePublic()
const searchKey = ref('')
const companyAll = ref<string[]>([])

const fetchCompanies = async () => {
	const res: any = await Storehouse_StockOut_Company_Name_List({User_tokey: globalStore.GET_User_tokey, T_name: searchKey.value || ''})
	companyAll.value = res?.Data || []
}

// 右侧公司设备统计
interface RowItem {
	seq?: number
	out_number?: string
	product_name?: string
	device_sn?: string
	num?: number
	unit?: string
	remark?: string
	return_number?: string
	return_device_sn?: string
	return_remark?: string
}

interface DeviceStatItem {
	out_total: number
	return_total: number
	rows: RowItem[]
}

const activeCompany = ref('')
const deviceList = ref<DeviceStatItem[]>([])

// 右表加载状态
const rightLoading = ref(false)

const flatRows = computed(() => {
	// 拍平数据，同时将缺省 out_number/product_name 继承为上一条的值，便于合并
	const result: any[] = []
	deviceList.value.forEach((g) => {
		let currentOut = ''
		let currentProduct = ''
		g.rows.forEach((r: any) => {
			if (r.out_number) {
				currentOut = r.out_number
				if (r.product_name) currentProduct = r.product_name
			} else {
				r.out_number = currentOut
				if (!r.product_name) r.product_name = currentProduct
			}
			if (!r.product_name && currentProduct) r.product_name = currentProduct
			result.push({...r})
		})
	})
	return result
})

// 计算单号合并跨度
const outSpanMap = computed(() => {
	const map = new Map<number, number>()
	const list = flatRows.value
	let i = 0
	while (i < list.length) {
		let j = i + 1
		while (j < list.length && list[j].out_number === list[i].out_number) j++
		map.set(i, j - i)
		i = j
	}
	return map
})

// 计算品名在同一单号内的合并跨度
const productSpanMap = computed(() => {
	const map = new Map<number, number>()
	const list = flatRows.value
	let i = 0
	while (i < list.length) {
		let j = i + 1
		while (j < list.length && list[j].out_number === list[i].out_number) j++ // [i, j) 为同一出库单
		let start = i
		while (start < j) {
			let k = start + 1
			while (k < j && list[k].product_name === list[start].product_name) k++
			map.set(start, k - start)
			start = k
		}
		i = j
	}
	return map
})

// 表格合并策略
const spanMethod = ({ column, rowIndex }: any) => {
	if (column?.property === 'out_number'|| column?.property === 'remark') {
		const span = outSpanMap.value.get(rowIndex) || 0
		return span > 0 ? { rowspan: span, colspan: 1 } : { rowspan: 0, colspan: 0 }
	}
	if (column?.property === 'product_name' || column?.property === 'num' || column?.property === 'unit') {
		const span = productSpanMap.value.get(rowIndex) || 0
		return span > 0 ? { rowspan: span, colspan: 1 } : { rowspan: 0, colspan: 0 }
	}
	return { rowspan: 1, colspan: 1 }
}

// 退回 SN 行：仅设备编号高亮，行本身不变

const outTotal = computed(() => deviceList.value.reduce((s, i) => s + (i.out_total || 0), 0))
const returnTotal = computed(() => deviceList.value.reduce((s, i) => s + (i.return_total || 0), 0))

// 右侧滚动加载（对拍平后的行做前端增量渲染）
const rightDisplayCount = ref(80)
const rightPageSize = 80
const rightVisibleRows = computed(() => flatRows.value.slice(0, rightDisplayCount.value))
const canLoadMoreRight = computed(() => rightDisplayCount.value < flatRows.value.length)
const onRightScroll = (e: Event) => {
	const el = e.target as HTMLElement
	if (!el) return
	if (el.scrollTop + el.clientHeight >= el.scrollHeight - 10 && canLoadMoreRight.value) {
		rightDisplayCount.value = Math.min(rightDisplayCount.value + rightPageSize, flatRows.value.length)
	}
}

const fetchDeviceStats = async (company?: string) => {
	if (!company) return
	try {
		rightLoading.value = true
		const res: any = await Storehouse_Company_Device_Statistics({User_tokey: globalStore.GET_User_tokey, T_company_name: company})
		deviceList.value = Array.isArray(res?.Data) ? res.Data : []
		// 重置右侧滚动加载
		rightDisplayCount.value = rightPageSize
	} finally {
		rightLoading.value = false
	}
}

const onSelectCompany = (name: string) => {
	activeCompany.value = name
	fetchDeviceStats(name)
}

// 导出
const exporting = ref(false)
const exportExcel = async () => {
	if (!activeCompany.value) {
		ElMessage.warning('请选择公司后再导出')
		return
	}
	try {
		exporting.value = true
		const response: any = await Storehouse_Company_Device_Statistics_Excel({
			User_tokey: globalStore.GET_User_tokey,
			T_company_name: activeCompany.value
		})
		// 兼容两种返回：1) blob 文件；2) json { Code, Data: 'url' }
		if (response instanceof Blob) {
			try {
				const text = await response.text()
				const json = JSON.parse(text)
				if (json?.Data) {
					window.open(json.Data)
				} else {
					// 非 JSON，按文件下载
					const blob = new Blob([text], {type: 'application/vnd.ms-excel;charset=utf8'})
					const url = window.URL.createObjectURL(blob)
					const a = document.createElement('a')
					a.href = url
					const now = new Date()
					const ts = `${now.getFullYear()}${(now.getMonth() + 1).toString().padStart(2, '0')}${now.getDate().toString().padStart(2, '0')}_${now.getHours().toString().padStart(2, '0')}${now.getMinutes().toString().padStart(2, '0')}`
					a.download = `公司设备借出退回统计_${activeCompany.value}_${ts}.xlsx`
					document.body.appendChild(a)
					a.click()
					a.remove()
					window.URL.revokeObjectURL(url)
				}
			} catch (_) {
				const url = window.URL.createObjectURL(response)
				const a = document.createElement('a')
				a.href = url
				const now = new Date()
				const ts = `${now.getFullYear()}${(now.getMonth() + 1).toString().padStart(2, '0')}${now.getDate().toString().padStart(2, '0')}_${now.getHours().toString().padStart(2, '0')}${now.getMinutes().toString().padStart(2, '0')}`
				a.download = `公司设备借出退回统计_${activeCompany.value}_${ts}.xlsx`
				document.body.appendChild(a)
				a.click()
				a.remove()
				window.URL.revokeObjectURL(url)
			}
		} else if (response?.Code === 200 && response?.Data) {
			window.open(response.Data)
		} else {
			ElMessage.error('导出失败：未知返回格式')
		}
		ElMessage.success('导出成功')
	} catch (e) {
		ElMessage.error('导出失败，请稍后重试')
	} finally {
		exporting.value = false
	}
}

onMounted(() => {
	fetchCompanies()
})
</script>

<template>
	<div class="company-device-stat">
		<div class="left-list">
			<div class="left-header">
				<h3 class="title">公司名称</h3>
				<el-input v-model="searchKey" placeholder="按公司名称搜索" clearable @change="fetchCompanies" />
			</div>
			<div class="company-scroll">
				<el-empty v-if="companyAll.length === 0" description="无数据" />
				<el-menu :default-active="activeCompany" class="company-menu" :collapse="false">
					<el-menu-item v-for="name in companyAll" :key="name" :index="name" @click="onSelectCompany(name)">
						{{ name.trim() }}
					</el-menu-item>
				</el-menu>
			</div>
		</div>

		<div class="right-content" v-if="activeCompany">
			<div class="toolbar">
				<h3 class="title">{{ activeCompany }} 设备借出/退回统计</h3>
				<div class="actions">
					<el-button type="success" :loading="exporting" @click="exportExcel">导出</el-button>
				</div>
			</div>
			<el-card class="box-card">
				<div class="stat-info">
					<span>借出总数：<b>{{ outTotal }}</b></span>
					<span>退回总数：<b>{{ returnTotal }}</b></span>
				</div>
                <div class="right-table-scroll" @scroll="onRightScroll">
                <el-table :data="rightVisibleRows" v-loading="rightLoading" style="width: 100%" :span-method="spanMethod" size="small">
					<el-table-column type="index" label="序号" width="60" align="center" />
					<el-table-column prop="out_number" label="出库单号" width="160" align="center" show-overflow-tooltip />
					<el-table-column prop="product_name" label="品名" width="220" align="center" show-overflow-tooltip />
                    <el-table-column prop="device_sn" label="设备SN" width="180" align="center" show-overflow-tooltip>
                        <template #default="{ row }">
                            <span :class="row.return_device_sn ? 'sn-danger' : ''">{{ row.device_sn }}</span>
                        </template>
                    </el-table-column>
					<el-table-column prop="num" label="数量" width="80" align="center" />
					<el-table-column prop="unit" label="单位" width="80" align="center" />
					<el-table-column prop="remark" label="备注" width="160" align="center" show-overflow-tooltip />
					<el-table-column prop="return_number" label="退回单号" width="160" align="center" show-overflow-tooltip />
					<el-table-column prop="return_device_sn" label="退回SN" width="180" align="center" show-overflow-tooltip />
					<el-table-column prop="return_remark" label="退回备注" width="160" align="center" show-overflow-tooltip />
					<template #empty>
						<el-empty description="暂无数据" />
					</template>
				</el-table>
				<div v-if="canLoadMoreRight" class="right-loading-more">下拉加载更多...</div>
				</div>
			</el-card>
		</div>
	</div>
</template>

<style scoped lang="scss">
@import '@/styles/var.scss';
.company-device-stat {
	height: 100%;
	display: flex;
	overflow: hidden;
	.title {
		width: 100%;
		text-align: center;
		line-height: 1.7em;
		font-size: 20px;
		color: #707b84;
	}
	.left-list {
		@include f-direction;
		width: 290px;
		z-index: 1;
		.left-header { padding: 2px; }
			.company-scroll {
			height: calc(100% - 90px);
			overflow: auto;
			.company-menu { width: 100%; border-right: none; }
			:deep(.el-menu-item){
				line-height: 40px;
				height: 40px;
				padding: 0 15px;
				color: var(--el-text-color-regular);
			}
			:deep(.el-menu-item:hover){
				background-color: var(--el-color-primary-light-9);
			}
			:deep(.el-menu-item.is-active){
				// background-color: var(--el-color-primary-light-7);
				color: var(--el-color-primary);
				font-weight: 600;
			}
		}
	}
	.right-content {
		@include f-direction;
		z-index: 0;
		margin-left: 12px;
		width: calc(100% - 290px);
		.toolbar {
			display: flex;
			justify-content: space-between;
			align-items: center;
			margin-bottom: 8px;
		}
		.box-card { border-radius: 8px; }
		.stat-info { display: flex; gap: 16px; padding: 6px 0 12px 0; }
		/* 右侧表格行距再小一些：对 tbody 行强制最小高度与内边距 */
		:deep(.el-table){ --el-table-row-height: 26px; }
		:deep(.el-table__body tr){ height: 24px; }
		:deep(.el-table .cell){ padding: 2px 6px; line-height: 20px; }
		.right-table-scroll { max-height: calc(100vh - 260px); overflow: auto; }
		.right-loading-more { text-align: center; color: #999; padding: 8px 0; }
        /* 仅退回SN的设备编号标红 */
        :deep(.sn-danger){ color: var(--el-color-danger); }
	}
}
</style>
