<template>
  <div
    ref="fullscreenTargetRef"
    class="run-overview-page"
    :class="{ 'is-fullscreen': isFullscreen }"
  >
    <div class="run-overview-page__floating-tools">
      <el-tooltip
        :content="
          isFullscreen
            ? t('DataCollection.RunOverview.exitFullscreen')
            : t('DataCollection.RunOverview.enterFullscreen')
        "
      >
        <button class="run-overview-page__screenfull" type="button" @click="toggleFullscreen">
          <Icon :icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'" color="#344054" />
        </button>
      </el-tooltip>
    </div>

    <OverviewFilterBar
      v-model="queryParams"
      :group-options="groupOptions"
      :device-options="deviceOptions"
      :quick-ranges="quickRanges"
      @quick-range-change="handleQuickRangeChange"
      @query="handleQuery"
      @reset="resetQuery"
    />

    <OverviewMetricCards :metrics="overviewData.metrics" />

    <StatusDistributionChart
      :hourly-status="overviewData.hourlyStatus"
      :summary="overviewData.summary"
      :summary-total-hours="overviewData.summaryTotalHours"
    />

    <OperationTimelineChart
      :rows="overviewData.timelineRows"
      :total="overviewData.totalDevices"
      :page-no="pageNo"
      :page-size="pageSize"
      :statistics-start="queryParams.timeRange[0]"
      :statistics-end="queryParams.timeRange[1]"
      @update:page-no="pageNo = $event"
      @update:page-size="handlePageSizeChange"
    />
  </div>
</template>

<script setup lang="ts">
import dayjs from 'dayjs'
import { useFullscreen } from '@vueuse/core'
import { DeviceOperationOverviewApi } from '@/api/iot/deviceOperationOverview'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { DeviceLineApi, DeviceLineTreeVO } from '@/api/mes/deviceline'
import OverviewFilterBar from './components/OverviewFilterBar.vue'
import OverviewMetricCards from './components/OverviewMetricCards.vue'
import OperationTimelineChart from './components/OperationTimelineChart.vue'
import StatusDistributionChart from './components/StatusDistributionChart.vue'
import { buildDefaultQueryParams } from './mock'
import type {
  OrganizationTreeOption,
  OverviewOption,
  QuickRangeKey,
  RunOverviewData,
  RunOverviewQueryParams
} from './components/types'

defineOptions({ name: 'IotRunOverview' })

const { t } = useI18n()
const message = useMessage()
const fullscreenTargetRef = ref()
const { isFullscreen, toggle: toggleFullscreen } = useFullscreen(fullscreenTargetRef)
const deviceLedgerList = ref<DeviceLedgerVO[]>([])
const groupOptions = ref<OrganizationTreeOption[]>([])

const createDateRangeByQuickKey = (key: QuickRangeKey): [string, string] => {
  const format = 'YYYY-MM-DD HH:mm:ss'
  if (key === 'today')
    return [dayjs().startOf('day').format(format), dayjs().endOf('day').format(format)]
  if (key === 'yesterday') {
    return [
      dayjs().subtract(1, 'day').startOf('day').format(format),
      dayjs().subtract(1, 'day').endOf('day').format(format)
    ]
  }
  if (key === 'last7Days')
    return [
      dayjs().subtract(6, 'day').startOf('day').format(format),
      dayjs().endOf('day').format(format)
    ]
  if (key === 'last30Days') {
    return [
      dayjs().subtract(29, 'day').startOf('day').format(format),
      dayjs().endOf('day').format(format)
    ]
  }
  return [dayjs().startOf('day').format(format), dayjs().endOf('day').format(format)]
}

const quickRanges = computed(() => [
  { label: t('DataCollection.RunOverview.quickRange.today'), value: 'today' as const },
  { label: t('DataCollection.RunOverview.quickRange.yesterday'), value: 'yesterday' as const },
  { label: t('DataCollection.RunOverview.quickRange.last7Days'), value: 'last7Days' as const },
  { label: t('DataCollection.RunOverview.quickRange.last30Days'), value: 'last30Days' as const }
  /*  { label: t('DataCollection.RunOverview.quickRange.custom'), value: 'custom' as const }*/
])

const queryParams = ref<RunOverviewQueryParams>(buildDefaultQueryParams())
const pageNo = ref(1)
const pageSize = ref(10)

const normalizeDeviceLineTree = (nodes: DeviceLineTreeVO[] = []): OrganizationTreeOption[] =>
  nodes.map((node) => ({
    id: String(node.id),
    name: node.name,
    parentId: node.parentId != null ? String(node.parentId) : node.parentId,
    children: Array.isArray(node.children) ? normalizeDeviceLineTree(node.children) : undefined
  }))

const collectGroupIds = (groupId?: string) => {
  if (!groupId) return undefined
  const ids = new Set<string>()
  const stack = [...groupOptions.value]

  while (stack.length > 0) {
    const node = stack.pop()!
    if (String(node.id) === groupId) {
      const collectStack = [node]
      while (collectStack.length > 0) {
        const current = collectStack.pop()!
        ids.add(String(current.id))
        if (Array.isArray(current.children)) collectStack.push(...current.children)
      }
      break
    }
    if (Array.isArray(node.children)) stack.push(...node.children)
  }

  return ids
}

const hasIotDeviceCode = (item: DeviceLedgerVO) => String(item.iotDeviceCode ?? '').trim() !== ''

const getDeviceOptionLabel = (item: DeviceLedgerVO) => {
  const deviceName = String(item.deviceName ?? '').trim()
  const deviceCode = String(item.deviceCode ?? '').trim()
  return deviceName || deviceCode || String(item.iotDeviceName ?? item.iotDeviceCode ?? '').trim()
}

const collectDeviceOptionsByGroup = (groupId?: string) => {
  const deviceMap = new Map<string, OverviewOption>()
  const groupIds = collectGroupIds(groupId)
  deviceLedgerList.value.forEach((item) => {
    if (groupIds && !groupIds.has(String(item.deviceLine ?? ''))) return
    const deviceCode = String(item.iotDeviceCode ?? '').trim()
    if (!deviceCode || deviceMap.has(deviceCode)) return
    deviceMap.set(deviceCode, {
      label: getDeviceOptionLabel(item),
      value: deviceCode
    })
  })
  return Array.from(deviceMap.values())
}
const deviceOptions = computed(() => collectDeviceOptionsByGroup(queryParams.value.groupId))
const overviewData = ref<RunOverviewData>({
  metrics: [],
  hourlyStatus: [],
  summary: [],
  summaryTotalHours: 0,
  timelineRows: [],
  totalDevices: 0
})

const currentDeviceIds = computed(() =>
  queryParams.value.deviceId.length > 0
    ? queryParams.value.deviceId
    : deviceOptions.value.map((item) => item.value)
)

const buildOverviewRequestParams = () => ({
  ids: currentDeviceIds.value.join(','),
  startTime: queryParams.value.timeRange[0],
  endTime: queryParams.value.timeRange[1],
  timelinePageNo: pageNo.value,
  timelinePageSize: pageSize.value
})

const refreshData = async () => {
  const response = await DeviceOperationOverviewApi.getRunOverview(buildOverviewRequestParams())
  overviewData.value = {
    metrics: response?.metrics || [],
    hourlyStatus: response?.hourlyStatus || [],
    summary: response?.summary || [],
    summaryTotalHours: response?.summaryTotalHours || 0,
    timelineRows: response?.timelineRows || [],
    totalDevices: response?.totalDevices || 0
  }
  const maxPage = Math.max(1, Math.ceil(overviewData.value.totalDevices / pageSize.value))
  if (pageNo.value > maxPage) pageNo.value = maxPage
}

const resetToFirstPageAndRefresh = () => {
  if (pageNo.value !== 1) {
    pageNo.value = 1
    return
  }
  void refreshData()
}

const handleQuickRangeChange = (key: QuickRangeKey) => {
  queryParams.value = {
    ...queryParams.value,
    quickRange: key,
    timeRange: createDateRangeByQuickKey(key)
  }
  pageNo.value = 1
}

const handleQuery = () => {
  resetToFirstPageAndRefresh()
}

const resetQuery = () => {
  queryParams.value = buildDefaultQueryParams()
  pageSize.value = 10
  resetToFirstPageAndRefresh()
}

const handleExport = () => {
  message.success(t('DataCollection.RunOverview.exportPlaceholderMessage'))
}

const handlePageSizeChange = (size: number) => {
  pageSize.value = size
  pageNo.value = 1
  void refreshData()
}

watch(pageNo, () => {
  void refreshData()
})

const getFilterOptions = async () => {
  const [deviceLineTree, ledgerList] = await Promise.all([
    DeviceLineApi.getDeviceLineTree(),
    DeviceLedgerApi.getDeviceLedgerList()
  ])
  groupOptions.value = normalizeDeviceLineTree(Array.isArray(deviceLineTree) ? deviceLineTree : [])
  deviceLedgerList.value = Array.isArray(ledgerList) ? ledgerList.filter(hasIotDeviceCode) : []
}
watch(
  deviceOptions,
  (options) => {
    if (queryParams.value.deviceId.length === 0) return
    const validDeviceIds = queryParams.value.deviceId.filter((deviceId) =>
      options.some((item) => item.value === deviceId)
    )
    if (validDeviceIds.length !== queryParams.value.deviceId.length) {
      queryParams.value = {
        ...queryParams.value,
        deviceId: validDeviceIds
      }
    }
  },
  { immediate: true }
)

onMounted(async () => {
  await getFilterOptions()
  await refreshData()
})
</script>

<style scoped lang="scss">
.run-overview-page {
  position: relative;
  min-width: 0;
  //padding-top: 8px;
}

.run-overview-page.is-fullscreen {
  height: 100%;
  padding: 16px;
  overflow: auto;
  background: #f5f7fa;
}

.run-overview-page__floating-tools {
  position: absolute;
  top: 8px;
  right: 12px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 8px;
}

.run-overview-page__screenfull {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  background: #fff;
  border: 1px solid #e4e7ec;
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.08);
  cursor: pointer;
  transition: all 0.2s ease;
}

.run-overview-page__screenfull:hover {
  background: #f8fbff;
  border-color: #bfd3ff;
  box-shadow: 0 8px 18px rgba(61, 132, 255, 0.12);
}
</style>
