<template>
  <div class="mod-weather__real-time-monitoring" v-loading="state.loading">
    <div class="page-header">
      <div>
        <h2 class="page-title">631气象信息</h2>
      </div>
      <div class="page-header-actions">
        <el-tag type="info">层级 {{ state.selectedPath.length }} 级</el-tag>
        <el-tag type="success">文件 {{ state.fileItems.length }}</el-tag>
        <el-button type="primary" plain icon="Refresh" @click="refresh">刷新</el-button>
      </div>
    </div>

    <el-alert v-if="state.errorMessage" :title="state.errorMessage" type="error" :closable="false" show-icon class="mb-16" />

    <div class="dept-bar" v-if="levelRows.length">
      <div class="level-row" v-for="(row, rowIdx) in levelRows" :key="rowIdx">
        <span class="level-label" v-if="row.label">{{ row.label }}</span>
        <div class="level-tabs">
          <div v-for="tab in row.tabs" :key="tab.id" class="level-tab" :class="[{ 'is-active': row.selectedId === tab.id }, `level-${rowIdx}`]" @click="selectTab(rowIdx, tab)">
            {{ tab.name }}
          </div>
        </div>
      </div>
    </div>

    <div class="page-body" v-if="state.fileItems.length">
      <aside class="file-list-panel">
        <div v-for="(item, index) in state.fileItems" :key="item.anchorId" class="file-list-item" :class="{ 'is-active': state.selectedFileIndex === index }" @click="selectFile(index)">
          <div class="file-list-item__thumb">
            <span class="file-list-item__icon file-list-item__icon--txt">文</span>
          </div>
          <span class="file-list-item__name">{{ item.displayName || `文件-${item.fileId}` }}</span>
        </div>
      </aside>

      <section class="preview-panel" v-if="previewItem">
        <div class="preview-panel__header">
          <h3 class="preview-panel__title">{{ previewItem.displayName || `文件-${previewItem.fileId}` }}</h3>
          <el-button type="primary" plain size="small" :loading="state.copyingId === previewItem.anchorId" @click="copyText(previewItem)"> 复制全部文本 </el-button>
        </div>

        <div class="preview-panel__body">
          <div class="preview-panel__text preview-panel__text--full">{{ previewItem.content || "暂无文本内容" }}</div>
        </div>
      </section>

      <div class="preview-panel preview-panel--empty" v-else>
        <el-empty description="请在左侧选择要预览的文件" :image-size="120" />
      </div>
    </div>

    <el-empty v-else-if="!state.loading && !state.errorMessage" description="暂无可供展示的文件" />
  </div>
</template>

<script lang="ts" setup>
import app from "@/constants/app";
import baseService from "@/service/baseService";
import { copyToClipboard } from "@/utils/utils";
import { ElMessage } from "element-plus";
import { computed, onMounted, reactive } from "vue";

interface DeptNode {
  id: string;
  name: string;
  children?: DeptNode[];
}

interface DeptTab {
  id: string;
  name: string;
}

interface DeptFileGroupVO {
  deptId: string;
  deptName: string;
  fileList: { displayName: string; fileId: string; type: string; content: string }[];
}

interface FileItem {
  deptId: string;
  deptName: string;
  displayName: string;
  fileId: string;
  type: string;
  content: string;
  anchorId: string;
}

const IMAGE_EXTS = ["png", "jpg", "jpeg", "gif", "bmp", "webp", "svg"];

const isImageFile = (type: string) => {
  if (!type) return true;
  const lower = type.toLowerCase();
  return IMAGE_EXTS.some((ext) => lower.includes(ext));
};

const state = reactive({
  loading: true,
  errorMessage: "",
  fileItems: [] as FileItem[],
  copyingId: "",
  deptTreeData: [] as DeptNode[],
  selectedPath: [] as string[],
  selectedFileIndex: 0
});

const previewItem = computed(() => {
  if (state.selectedFileIndex >= 0 && state.selectedFileIndex < state.fileItems.length) {
    return state.fileItems[state.selectedFileIndex];
  }
  return state.fileItems.length > 0 ? state.fileItems[0] : null;
});

const transformGroups = (list: DeptFileGroupVO[]) => {
  const items: FileItem[] = [];

  list.forEach((group) => {
    (group.fileList || []).forEach((file) => {
      if (isImageFile(file.type)) return;
      items.push({
        deptId: group.deptId,
        deptName: group.deptName,
        displayName: file.displayName,
        fileId: file.fileId,
        type: file.type,
        content: file.content || "",
        anchorId: `txt-${file.fileId}`
      });
    });
  });

  state.fileItems = items;
  state.selectedFileIndex = 0;
};

const activeDeptId = computed(() => {
  if (state.selectedPath.length > 0) {
    return state.selectedPath[state.selectedPath.length - 1];
  }
  return null;
});

interface LevelRow {
  tabs: DeptTab[];
  selectedId: string | null;
  label: string;
}

const LEVEL_LABELS = ["一级", "二级", "三级", "四级", "五级", "六级"];

const levelRows = computed<LevelRow[]>(() => {
  const rows: LevelRow[] = [];
  let nodes: DeptNode[] = state.deptTreeData;

  for (let i = 0; i < state.selectedPath.length; i++) {
    const selId = state.selectedPath[i];
    rows.push({
      tabs: nodes.map((n) => ({ id: n.id, name: n.name })),
      selectedId: selId,
      label: LEVEL_LABELS[i] || `${i + 1}级`
    });
    const selNode = nodes.find((n) => n.id === selId);
    if (selNode?.children?.length) {
      nodes = selNode.children;
    } else {
      nodes = [];
      break;
    }
  }

  if (nodes.length > 0) {
    rows.push({
      tabs: nodes.map((n) => ({ id: n.id, name: n.name })),
      selectedId: null,
      label: LEVEL_LABELS[rows.length] || `${rows.length + 1}级`
    });
  }

  return rows;
});

const loadData = async (deptId: string) => {
  state.loading = true;
  state.errorMessage = "";
  try {
    const res = await baseService.get("/filescan/record/tree", { deptId });
    transformGroups((res.data || []) as DeptFileGroupVO[]);
    selectFile(0);
  } catch (error: any) {
    state.errorMessage = error?.message || "加载失败";
    state.fileItems = [];
  } finally {
    state.loading = false;
  }
};

const loadDeptTree = async (): Promise<string | null> => {
  try {
    const res = await baseService.get("/sys/dept/list");
    const treeData = (res.data || []) as DeptNode[];
    state.deptTreeData = treeData;

    if (!treeData.length) return null;

    const firstRoot = treeData[0];
    const firstChild = firstRoot.children?.length ? firstRoot.children[0] : firstRoot;

    const buildPath = (nodes: DeptNode[], targetId: string, path: string[]): string[] | null => {
      for (const node of nodes) {
        const newPath = [...path, node.id];
        if (node.id === targetId) return newPath;
        if (node.children?.length) {
          const found = buildPath(node.children, targetId, newPath);
          if (found) return found;
        }
      }
      return null;
    };

    const path = buildPath(treeData, firstChild.id, []);
    state.selectedPath = path || [firstRoot.id];
    return firstChild.id;
  } catch {
    state.deptTreeData = [];
    return null;
  }
};

const selectTab = (levelIdx: number, tab: DeptTab) => {
  state.selectedPath = [...state.selectedPath.slice(0, levelIdx), tab.id];
  state.fileItems = [];
  state.selectedFileIndex = 0;
  loadData(tab.id);
};

const refresh = () => {
  if (activeDeptId.value !== null) {
    loadData(activeDeptId.value);
  }
};

const selectFile = (index: number) => {
  state.selectedFileIndex = index;
};

const copyText = (item: FileItem) => {
  state.copyingId = item.anchorId;
  copyToClipboard(item.content || "");
  ElMessage.success("文本已复制成功");
  state.copyingId = "";
};

onMounted(async () => {
  const deptId = await loadDeptTree();
  if (deptId !== null) {
    loadData(deptId);
  }
});
</script>

<style scoped>
.mod-weather__real-time-monitoring {
  min-height: calc(100vh - 140px);
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 16px;
}

.page-title {
  margin: 0;
  font-size: 24px;
  color: #303133;
}

.page-desc {
  margin: 8px 0 0;
  color: #909399;
  line-height: 1.6;
}

.page-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.mb-16 {
  margin-bottom: 16px;
}

/* ==== 部门选择栏 ==== */
.dept-bar {
  margin-bottom: 16px;
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  padding: 10px 16px 8px;
}

.level-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.level-row:last-child {
  margin-bottom: 4px;
}

.level-label {
  font-size: 13px;
  color: #909399;
  flex-shrink: 0;
  min-width: 32px;
}

.level-tabs {
  display: flex;
  gap: 0;
  flex-wrap: wrap;
}

.level-tab {
  padding: 4px 16px;
  font-size: 13px;
  color: #606266;
  background: #f5f7fa;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
}

.level-tab + .level-tab {
  margin-left: 6px;
}

.level-tab:hover {
  color: var(--el-color-primary);
  background: #ecf5ff;
}

.level-tab.is-active {
  color: #fff;
  font-weight: 500;
}

.level-tab.is-active.level-0 {
  background: var(--el-color-primary);
  border-color: var(--el-color-primary);
}

.level-tab.is-active.level-1 {
  background: var(--el-color-primary-light-3);
  border-color: var(--el-color-primary-light-3);
}

.level-tab.is-active.level-2 {
  background: var(--el-color-success);
  border-color: var(--el-color-success);
}

.level-tab.is-active.level-3 {
  background: var(--el-color-warning);
  border-color: var(--el-color-warning);
}

.level-tab.is-active.level-4 {
  background: var(--el-color-danger);
  border-color: var(--el-color-danger);
}

.level-tab.is-active.level-5 {
  background: #8b5cf6;
  border-color: #8b5cf6;
}

/* ==== 主体两栏 ==== */
.page-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}

/* ==== 左侧文件列表 ==== */
.file-list-panel {
  position: sticky;
  top: 16px;
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 8px;
  padding: 4px;
  max-height: calc(100vh - 320px);
  overflow-y: auto;
}

.file-list-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  font-size: 13px;
  color: #606266;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.file-list-item:hover {
  background: #f5f7fa;
}

.file-list-item.is-active {
  background: var(--el-color-primary-light-9);
  color: var(--el-color-primary);
  font-weight: 500;
}

.file-list-item__thumb {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 6px;
  overflow: hidden;
  background: #f0f2f5;
  display: flex;
  align-items: center;
  justify-content: center;
}

.file-list-item__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.file-list-item__icon {
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.file-list-item__icon--img {
  background: var(--el-color-success);
}

.file-list-item__icon--txt {
  background: var(--el-color-warning);
}

.file-list-item__icon--other {
  background: #c0c4cc;
}

.file-list-item__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.5;
}

/* ==== 右侧预览面板 ==== */
.preview-panel {
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 10px;
  padding: 20px;
}

.preview-panel--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
}

.preview-panel__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  margin-bottom: 16px;
}

.preview-panel__actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.preview-panel__title {
  margin: 0;
  font-size: 20px;
  color: #303133;
  word-break: break-all;
}

.preview-panel__body {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.preview-panel__loading {
  text-align: center;
  color: #909399;
  padding: 60px 0;
  font-size: 14px;
}

.preview-zoom-area {
  overflow: hidden;
  border-radius: 8px;
  background: #f5f7fa;
  min-height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.preview-panel__img {
  display: block;
  max-width: 100%;
  max-height: 60vh;
  border-radius: 8px;
  user-select: none;
  pointer-events: auto;
}

.preview-panel__text--full {
  min-height: 200px;
  max-height: 60vh;
  overflow-y: auto;
}

.preview-panel__text {
  font-size: 13px;
  color: #606266;
  line-height: 1.8;
  white-space: pre-wrap;
  word-break: break-word;
  padding: 12px 14px;
  background: #f5f7fa;
  border-radius: 8px;
}

.image-card__error,
.image-card__unsupported {
  color: #e6a23c;
  font-size: 14px;
  line-height: 1.6;
  padding: 12px 14px;
  background: #fdf6ec;
  border-radius: 8px;
}

/* ==== 响应式 ==== */
@media (max-width: 992px) {
  .page-body {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .page-header,
  .preview-panel__header,
  .preview-panel__actions {
    flex-direction: column;
    align-items: stretch;
  }

  .level-tab {
    padding: 4px 10px;
    font-size: 12px;
  }
}
</style>
