<script lang="ts">
function renderIcon(icon: Component): () => VNode {
  return () => h(NIcon, null, { default: () => h(icon) });
}
</script>

<script setup lang="ts">
import { SettingsDrawer, SyncCameraResultModal } from '@/components';
import { useStompClient } from '@/composables';
import { useLineStationsQuery } from '@/composables';
import { LINE_STATIONS_QUERY_KEY, LINE_DEVICES_QUERY_KEY, LINE_ALARMS_QUERY_KEY } from '@/constants';
import { useAlarmStore, useSettingStore, useUserStore } from '@/stores';
import { useIsFetching } from '@tanstack/vue-query';
import {
  AlertFilled,
  BugFilled,
  CaretDownFilled,
  DoubleLeftOutlined,
  DoubleRightOutlined,
  EnvironmentFilled,
  /* AreaChartOutlined, */ FileTextFilled,
  HddFilled,
  LogoutOutlined,
  SettingOutlined,
} from '@vicons/antd';
import type { AxiosError } from 'axios';
import { NBadge, NButton, NDropdown, NFlex, NIcon, NLayout, NLayoutContent, NLayoutFooter, NLayoutHeader, NLayoutSider, NMenu, NScrollbar, type DropdownOption, type MenuOption } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { computed, h, onBeforeMount, ref, watch, type Component, type VNode } from 'vue';
import { RouterLink, useRoute, useRouter } from 'vue-router';

const { syncCameraResult, afterCheckSyncCamera } = useStompClient();

const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);

const alarmStore = useAlarmStore();
const { unreadAlarmCount } = storeToRefs(alarmStore);

const settingStore = useSettingStore();
const { menuCollpased } = storeToRefs(settingStore);

const onToggleMenuCollapsed = () => {
  menuCollpased.value = !menuCollpased.value;
};

const { error: stationListQueryError } = useLineStationsQuery();

watch(stationListQueryError, (newStationListQueryError) => {
  if (newStationListQueryError) {
    window.$message.error(newStationListQueryError.message);
  }
});

const lineStationsFetchingCount = useIsFetching({ queryKey: [LINE_STATIONS_QUERY_KEY] });
const lineDevicesFetchingCount = useIsFetching({ queryKey: [LINE_DEVICES_QUERY_KEY] });
const lineAlarmsFetchingCount = useIsFetching({ queryKey: [LINE_ALARMS_QUERY_KEY] });
const fetchingCount = computed(() => {
  return lineStationsFetchingCount.value + lineDevicesFetchingCount.value + lineAlarmsFetchingCount.value;
});

onBeforeMount(() => {
  userStore.userGetInfo().catch((err) => window.$message.error((err as AxiosError).message));
});

const route = useRoute();
const router = useRouter();

const menuOptions = ref<MenuOption[]>([
  {
    label: () => h(RouterLink, { to: '/station' }, { default: () => '车站状态' }),
    key: '/station',
    icon: renderIcon(EnvironmentFilled),
  },
  {
    label: () => h(RouterLink, { to: '/device' }, { default: () => '设备诊断' }),
    key: '/device',
    icon: renderIcon(HddFilled),
  },
  {
    label: () => h(RouterLink, { to: '/alarm' }, { default: () => '设备告警' }),
    key: '/alarm',
    icon: renderIcon(AlertFilled),
  },
  // {
  //   label: () => h(RouterLink, { to: '/statistics' }, { default: () => '设备数据统计' }),
  //   key: '/statistics',
  //   icon: renderIcon(AreaChartOutlined),
  // },
  {
    label: '系统日志',
    key: '/log',
    icon: renderIcon(FileTextFilled),
    children: [
      {
        label: () => h(RouterLink, { to: '/log/vimp-log' }, { default: () => '视频平台日志' }),
        key: '/log/vimp-log',
      },
      {
        label: () => h(RouterLink, { to: '/log/call-log' }, { default: () => '上级调用日志' }),
        key: '/log/call-log',
      },
    ],
  },
  {
    label: () => h(RouterLink, { to: '/debug' }, { default: () => '调试' }),
    key: '/debug',
    icon: renderIcon(BugFilled),
    show: import.meta.env.DEV,
  },
]);

const dropdownOptions = ref<DropdownOption[]>([
  {
    label: '退出登录',
    key: 'logout',
    icon: renderIcon(LogoutOutlined),
    onClick: async () => {
      try {
        await userStore.userLogout();
        router.push('/login');
      } catch (_) {
        window.$message.error('退出登录失败');
      }
    },
  },
]);

const selectDropdownOption = (key: string, option: DropdownOption) => {
  if (typeof option['onClick'] === 'function') {
    option['onClick']();
  }
};

const routeToRoot = () => {
  router.push('/');
};

const routeToAlarmPage = () => {
  unreadAlarmCount.value = 0;
  if (route.path !== '/alarm') {
    router.push('/alarm');
  }
};

const settingsDrawerShow = ref(false);
const openSettingsDrawer = () => {
  settingsDrawerShow.value = true;
};
</script>

<template>
  <NScrollbar x-scrollable style="width: 100vw; height: 100vh">
    <NLayout has-sider :content-style="{ 'min-width': '1400px' }">
      <NLayoutSider bordered :collapsed="menuCollpased" collapse-mode="width" :collapsed-width="64" @update:collapsed="onToggleMenuCollapsed">
        <NFlex vertical justify="space-between" :size="0" style="height: 100%">
          <NMenu :collapsed="menuCollpased" :collapsed-width="64" :collapsed-icon-size="20" :value="route.path" :options="menuOptions" />
          <NButton block quaternary :focusable="false" @click="onToggleMenuCollapsed">
            <template #icon>
              <NIcon :component="menuCollpased ? DoubleRightOutlined : DoubleLeftOutlined" />
            </template>
          </NButton>
        </NFlex>
      </NLayoutSider>
      <NLayout :native-scrollbar="false">
        <NLayoutHeader bordered class="app-layout-header">
          <NFlex justify="space-between" align="center" :size="8" style="width: 100%; height: 100%">
            <NFlex>
              <div style="font-size: 16px; font-weight: 500; margin-left: 16px; cursor: pointer" @click="routeToRoot">网络设备管理平台</div>
              <NButton text size="tiny" :loading="fetchingCount > 0" />
            </NFlex>
            <NFlex align="center" :size="0" style="height: 100%">
              <NDropdown trigger="hover" show-arrow :options="dropdownOptions" @select="selectDropdownOption">
                <NButton :focusable="false" quaternary icon-placement="right" style="height: 100%">
                  <template #default>
                    <span>{{ userInfo?.nickName ?? '' }}</span>
                  </template>
                  <template #icon>
                    <NIcon :component="CaretDownFilled" />
                  </template>
                </NButton>
              </NDropdown>
              <NButton :focusable="false" quaternary @click="openSettingsDrawer" style="height: 100%">
                <template #icon>
                  <NIcon :component="SettingOutlined" />
                </template>
              </NButton>
            </NFlex>
          </NFlex>
        </NLayoutHeader>
        <NLayoutContent class="app-layout-content">
          <RouterView />
        </NLayoutContent>
        <NLayoutFooter bordered class="app-layout-footer">
          <NFlex :align="'center'" style="height: 100%; margin: 0 16px">
            <NBadge :value="unreadAlarmCount">
              <NButton secondary strong @click="routeToAlarmPage">
                <template #icon>
                  <NIcon :component="AlertFilled" />
                </template>
              </NButton>
            </NBadge>
          </NFlex>
        </NLayoutFooter>
      </NLayout>
    </NLayout>
  </NScrollbar>

  <SettingsDrawer v-model:show="settingsDrawerShow" />

  <SyncCameraResultModal :sync-camera-result="syncCameraResult" @after-leave="afterCheckSyncCamera" />
</template>

<style scoped lang="scss">
$layout-header-height: 48px;
$layout-footer-height: 48px;

.app-layout-header {
  height: $layout-header-height;
}

.app-layout-content {
  height: calc(100vh - $layout-header-height - $layout-footer-height);
}

.app-layout-footer {
  height: $layout-footer-height;
}
</style>
