<template>
  <div class="shiPinJianKongZhuanTi-page">
    <a-tabs
      v-model:activeKey="activeTab"
      :tabBarGutter="32"
      class="custom-tabs"
      @change="handleTabChange"
    >
      <template #rightExtra>
        <a-button type="default" class="mr-2" @click="handleAction">
          <template #icon><i class="iconfont icon-fenbu mr-1" /></template>
          查看分布
        </a-button>
      </template>

      <a-tab-pane v-for="tab in tabs" :key="tab.key">
        <template #tab> {{ tab.title }}({{ tab.data?.count_sttpCode || 0 }}) </template>
      </a-tab-pane>
    </a-tabs>

    <div class="tabs-content">
      <!-- 顶部标题和图标选择区域 -->
      <div class="content-header">
        <div class="header-left">
          <span class="title"> <a-divider type="vertical"></a-divider> 监控列表</span>
        </div>
        <div class="header-right">
          <a-radio-group v-model:value="viewLayout" button-style="solid">
            <a-radio-button v-if="monitorType === 'live'" value="1">
              <i class="iconfont icon-view1"></i>
            </a-radio-button>
            <a-radio-button value="4">
              <i class="iconfont icon-view4"></i>
            </a-radio-button>
            <a-radio-button value="6">
              <i class="iconfont icon-view6"></i>
            </a-radio-button>
            <a-radio-button value="9">
              <i class="iconfont icon-view9"></i>
            </a-radio-button>
          </a-radio-group>
        </div>
      </div>

      <!-- 主体内容区域 -->
      <div class="content-body">
        <!-- 左侧监控列表 -->
        <div class="left-panel">
          <!-- Radio切换：实时视频/录像 -->
          <div class="monitor-radio">
            <a-radio-group
              v-model:value="monitorType"
              button-style="solid"
              size="small"
              @change="handleMonitorTypeChange"
            >
              <a-radio-button value="live">实时视频</a-radio-button>
              <a-radio-button value="record">录像</a-radio-button>
            </a-radio-group>
          </div>

          <!-- 查询和状态筛选 -->
          <div class="search-bar">
            <a-input-search
              v-model:value="searchText"
              placeholder="输入关键字搜索"
              size="small"
              :style="{ flex: monitorType === 'record' ? '1' : '0 1 auto' }"
              allow-clear
            />
            <div v-if="monitorType === 'live'" class="status-filter">
              <a-tooltip title="在线">
                <div
                  class="status-btn"
                  :class="{ active: statusFilter === 'online' }"
                  @click="statusFilter = 'online'"
                >
                  <i class="iconfont icon-jiankongFill __online"></i>
                </div>
              </a-tooltip>
              <a-tooltip title="离线">
                <div
                  class="status-btn"
                  :class="{ active: statusFilter === 'offline' }"
                  @click="statusFilter = 'offline'"
                >
                  <i class="iconfont icon-jiankongFill"></i>
                </div>
              </a-tooltip>
            </div>
          </div>

          <!-- 树形结构 -->
          <div class="tree-container">
            <a-spin :spinning="treeLoading" wrapperClassName="tree-spin">
              <!-- 空状态显示 -->
              <div v-if="!treeData || treeData.length === 0" class="empty-tree">
                <a-empty description="暂无数据" />
              </div>

              <!-- 树形组件 -->
              <a-tree
                v-else
                v-model:expandedKeys="expandedKeys"
                v-model:checkedKeys="checkedKeys"
                :tree-data="treeData"
                :field-names="{ name: 'name', key: 'key', children: 'children' }"
                checkable
                block-node
                :show-icon="monitorType === 'live'"
                @check="handleTreeSelect"
              >
                <template #title="{ name, status, children }">
                  <span>
                    <!-- 只在实时视频模式且最后一层（没有children）显示在线/离线图标 -->
                    <template
                      v-if="
                        monitorType === 'live' && (!children || children.length === 0)
                      "
                    >
                      <i
                        v-if="status === 1"
                        class="iconfont icon-jiankongFill __online tree-status-icon"
                      ></i>
                      <i
                        v-else
                        class="iconfont icon-jiankongFill tree-status-icon offline"
                      ></i>
                    </template>
                    {{ name }}
                  </span>
                </template>
              </a-tree>
            </a-spin>
          </div>
        </div>

        <!-- 中间视频内容区域 -->
        <div class="center-panel">
          <div class="video-grid" :class="`layout-${viewLayout}`">
            <div v-for="index in parseInt(viewLayout)" :key="index" class="video-item">
              <LiveVideoBox
                :video-data="videoList[index - 1]"
                :monitor-type="monitorType"
                height="100%"
                @close="(nodeKey) => removeVideo(index - 1, nodeKey)"
              />
            </div>
          </div>
        </div>

        <!-- 右侧回放面板（仅录像模式显示） -->
        <div v-if="monitorType === 'record'" class="right-panel">
          <div class="replay-header">
            <span class="replay-title"><a-divider type="vertical" />回放列表</span>
          </div>
          <!-- 时间选择 -->
          <div class="date-picker">
            <a-range-picker
              v-model:value="dateRange"
              format="YYYY-MM-DD"
              style="width: 100%"
              :presets="DateSetting.RangeButton.days"
            />
          </div>

          <!-- 录像列表 -->
          <div class="record-list">
            <a-spin :spinning="recordLoading" wrapperClassName="record-spin">
              <!-- 空状态显示 -->
              <div v-if="!recordList || recordList.length === 0" class="empty-record">
                <a-empty />
              </div>

              <!-- 列表 -->
              <div v-else class="record-items">
                <div
                  class="record-item"
                  v-for="(item, index) in recordList"
                  :key="index"
                  @click="handlePlayRecord(item)"
                >
                  <div class="record-image-wrapper">
                    <a-image :src="item.imgPath" :preview="false" alt="" />
                  </div>
                  <div class="sp_btn"><i class="icon iconfont icon-play"></i></div>
                  <a-tooltip placement="top">
                    <template #title>
                      <div>{{ item.name }}</div>
                      <div>{{ dayjs(item.time).format("YYYY-MM-DD HH") }}</div>
                    </template>
                    <div class="record-info">
                      <div class="record-name">{{ item.name }}</div>
                      <div class="record-time">
                        {{ dayjs(item.time).format("YYYY-MM-DD HH") }}
                      </div>
                    </div>
                  </a-tooltip>
                </div>
              </div>
            </a-spin>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, watch } from "vue";
import { message } from "ant-design-vue";
import {
  baseMsstbprpt,
  envVdTreeGetKendoListCust,
  envVdRunDataGetKendoList,
} from "@/api/shiPinJianKong";
import type { Dayjs } from "dayjs";
import dayjs from "dayjs";
import { DateSetting } from "@/utils/enumeration";
import LiveVideoBox from "./components/LiveVideoBox.vue";

// Tab相关
const tabs = ref<any[]>([]);
const activeTab = ref<string>("");

// 视图布局选择（1/4/6/9宫格）
const viewLayout = ref<"1" | "4" | "6" | "9">("4");

// 监控类型（实时视频/录像）
const monitorType = ref<"live" | "record">("live");

// 搜索文本
const searchText = ref("");

// 状态筛选（在线/离线）
const statusFilter = ref<"online" | "offline">("online");

// 视频列表
const videoList = ref<any[]>(Array(9).fill(null));

// 移除视频
const removeVideo = (index: number, nodeKey?: string) => {
  const videoData = videoList.value[index];

  // 如果传入了 nodeKey，优先使用；否则从 videoData 中获取
  const keyToRemove = nodeKey || videoData?.key;

  // 如果有关联的节点key，则取消勾选
  if (keyToRemove) {
    // 从 checkedKeys 中移除该节点的 key（使用 filter 创建新数组以触发响应式）
    checkedKeys.value = checkedKeys.value.filter((key) => key !== keyToRemove);

    // 检查并移除不再需要的父节点
    removeUnnecessaryParentKeys(keyToRemove);
  }
  // 移除视频
  videoList.value[index] = null;
};

// 添加视频到列表
const addVideo = (videoData: any) => {
  const maxCount = parseInt(viewLayout.value);
  // 找到第一个空位
  const emptyIndex = videoList.value.findIndex(
    (v, i) => i < maxCount && (v === null || v === undefined)
  );
  if (emptyIndex !== -1) {
    videoList.value[emptyIndex] = videoData;
  } else if (videoList.value.filter((v, i) => i < maxCount).length < maxCount) {
    videoList.value.push(videoData);
  } else {
    // 如果满了，替换第一个
    videoList.value[0] = videoData;
  }
};

// 监听布局变化，调整视频列表长度
watch(viewLayout, (newLayout) => {
  const maxCount = parseInt(newLayout);
  // 确保数组长度足够
  while (videoList.value.length < maxCount) {
    videoList.value.push(null);
  }
});

// 树形数据
const expandedKeys = ref<string[]>([]);
const checkedKeys = ref<string[]>([]);
const treeData = ref<any[]>([]);
const originalTreeData = ref<any[]>([]); // 保存原始数据
const treeLoading = ref(false);
let currentRequestId = 0; // 用于追踪最新的请求ID

// 日期范围（默认前7天）
const dateRange = ref<[Dayjs, Dayjs]>([dayjs().subtract(7, "day"), dayjs()]);

// 录像列表
const recordLoading = ref(false);
const recordList = ref<any[]>([]);

// 加载录像列表
const loadRecordList = async () => {
  // 获取当前选中的节点keys
  if (!checkedKeys.value || checkedKeys.value.length === 0) {
    recordList.value = [];
    return;
  }

  recordLoading.value = true;
  try {
    // 将选中的key转换为原始的id
    const originalIds: string[] = [];

    // 递归查找原始id
    const findOriginalId = (nodes: any[], targetKey: string): string | null => {
      for (const node of nodes) {
        if (node.key === targetKey) {
          // 如果节点有原始id，使用原始id，否则使用name
          return node.id || node.stcd || node.name;
        }
        if (node.children && node.children.length > 0) {
          const found = findOriginalId(node.children, targetKey);
          if (found) return found;
        }
      }
      return null;
    };

    // 从原始数据中获取对应的原始id
    for (const key of checkedKeys.value) {
      const originalId = findOriginalId(originalTreeData.value, key);
      if (originalId) {
        originalIds.push(originalId);
      }
    }

    const params = {
      filter: {
        logic: "and",
        filters: [
          {
            field: "stcd",
            operator: "in",
            value: originalIds,
          },
          {
            field: "tm",
            operator: "gte",
            dataType: "date",
            value: dateRange.value[0].format("YYYY-MM-DD 00:00:00"),
          },
          {
            field: "tm",
            operator: "lte",
            dataType: "date",
            value: dateRange.value[1].format("YYYY-MM-DD 23:59:59"),
          },
        ],
      },
      sort: [{ field: "tm", dir: "desc" }],
    };

    const res = await envVdRunDataGetKendoList(params);

    if (res?.data?.data) {
      recordList.value = res.data.data.map((item: any) => ({
        name: item.name || item.stnm || "录像文件",
        time: item.tm ? dayjs(item.tm).format("YYYY-MM-DD HH:mm:ss") : "",
        ...item,
      }));

      // 如果有录像数据，默认播放第一个
      if (recordList.value.length > 0) {
        const firstRecord = recordList.value[0];
        // 使用 flpth 字段作为视频路径
        const videoPath = firstRecord.flpth || firstRecord.url || firstRecord.videoUrl;
        if (videoPath) {
          // 清空之前的视频
          videoList.value = Array(9).fill(null);
          // 添加第一个录像到中间区域
          addVideo({
            flnm: firstRecord.name,
            stnm: firstRecord.stnm,
            url: videoPath,
            ...firstRecord,
          });
        }
      }
    } else {
      recordList.value = [];
    }
  } catch (error) {
    recordList.value = [];
  } finally {
    recordLoading.value = false;
  }
};

// 处理按钮点击
const handleAction = () => {
  // TODO: 实现查看分布功能
};

// 播放录像
const handlePlayRecord = (record: any) => {
  // 使用 flpth 字段作为视频路径
  const videoPath = record.flpth || record.url || record.videoUrl;
  if (videoPath) {
    const maxCount = parseInt(viewLayout.value);

    // 检查是否已经添加过该录像
    const existingIndex = videoList.value.findIndex((v) => v && v.flnm === record.flnm);

    if (existingIndex !== -1) {
      return;
    }

    // 检查当前已播放的视频数量
    const currentVideoCount = videoList.value.filter((v, i) => i < maxCount && v !== null)
      .length;

    if (currentVideoCount >= maxCount) {
      message.warning(`视频数量已达上限(${maxCount})，请关闭已打开的视频或调整宫格布局`);
      return;
    }

    // 添加到空闲位置
    addVideo({
      flnm: record.name,
      stnm: record.stnm,
      url: videoPath,
      ...record,
    });
  }
};

const init = async () => {
  const params = {
    filter: {
      logic: "and",
      filters: [
        {
          field: "sttpFullPath",
          operator: "contains",
          dataType: "string",
          value: "VD,VD_",
        },
      ],
    },
    group: [
      { dir: "asc", field: "sttpCode" },
      { dir: "asc", field: "sttpName" },
    ],
    groupResultFlat: true,
  };

  let res = await baseMsstbprpt(params);

  if (res?.data?.data) {
    const _list: any[] = [];

    // 合并生态流量
    res.data.data.forEach((el: any) => {
      if (el?.sttpCode == "VD_EQ" || el?.sttpCode == "VD_EQS") {
        const found = _list.find((item: any) => Array.isArray(item.sttpCode));

        if (found) {
          found.count_sttpCode += el.count_sttpCode;
          found.count_sttpName += el.count_sttpName;
          found.sttpCode.push(el?.sttpCode);
          found.sttpCode_value.push(el?.sttpCode);
        } else {
          _list.push({
            ...el,
            sttpCode: [el?.sttpCode],
            sttpCode_value: [el?.sttpCode],
            sttpName: "生态流量",
            sttpName_value: "生态流量",
          });
        }
      } else if (el?.sttpCode != "VD_FPRD") {
        _list.push(el);
      }
    });

    const list =
      _list.sort((a: any, b: any) => b?.count_sttpCode - a?.count_sttpCode) ?? [];
    const totalCount = list.reduce((sum, item) => sum + item.count_sttpCode, 0);

    const allObject = {
      sttpCode: ["all"],
      sttpCode_value: ["all"],
      count_sttpCode: totalCount,
      count_sttpName: "全部",
      sttpName: "全部",
      sttpName_value: "全部",
    };

    list.unshift(allObject);

    // 转换为tabs格式
    tabs.value = list.map((item: any, index: number) => ({
      key: String(index),
      title: item.sttpName || item.sttpName_value,
      data: item,
    }));

    // 设置默认选中的tab
    if (tabs.value.length > 0) {
      activeTab.value = tabs.value[0].key;
    }

    // 初始化后加载第一个tab的树形数据
    if (tabs.value.length > 0) {
      initTree();
    }
  }
};

// 初始化树形数据
const initTree = async () => {
  // 生成新的请求ID
  const requestId = ++currentRequestId;

  // 获取当前选中tab的数据
  const currentTab = tabs.value.find((tab) => tab.key === activeTab.value);
  if (!currentTab) return;

  const sttpCodeValue = currentTab.data?.sttpCode_value || [];

  // 构建筛选条件
  const filters: any[] = [];

  // 录像模式不传status，只传sttpCode
  if (monitorType.value === "live") {
    // 实时视频模式：添加status筛选
    const statusValue = statusFilter.value === "online" ? 1 : 0;
    filters.push({
      field: "status",
      operator: "eq",
      dataType: "string",
      value: statusValue,
    });
  }

  // 如果不是"全部"tab，才添加sttpCode筛选
  if (sttpCodeValue[0] !== "all") {
    filters.push({
      field: "sttpCode",
      operator: "in",
      dataType: "string",
      value: [sttpCodeValue],
    });
  }

  const params = {
    filter: {
      logic: "and",
      filters,
    },
  };

  // 清空视频列表和勾选状态
  videoList.value = Array(9).fill(null);
  checkedKeys.value = [];
  expandedKeys.value = [];

  treeLoading.value = true;
  try {
    const res = await envVdTreeGetKendoListCust(params);

    // 检查是否是最新的请求，如果不是则忽略结果
    if (requestId !== currentRequestId) {
      return;
    }

    if (res?.data?.data) {
      // 为每个节点生成唯一的key
      let keyCounter = 0;
      const generateKey = (nodes: any[]) => {
        nodes.forEach((node) => {
          node.key = `key_${keyCounter++}`;
          if (node.children && node.children.length > 0) {
            generateKey(node.children);
          }
        });
      };

      generateKey(res.data.data);
      treeData.value = res.data.data;
      originalTreeData.value = JSON.parse(JSON.stringify(res.data.data)); // 深拷贝保存原始数据

      // 只展开第一条数据的所有子节点
      const getFirstBranchKeys = (nodes: any[]): string[] => {
        let keys: string[] = [];
        if (nodes.length > 0) {
          const firstNode = nodes[0];
          if (firstNode.children && firstNode.children.length > 0) {
            keys.push(firstNode.key);
            keys = keys.concat(getFirstBranchKeys(firstNode.children));
          }
        }
        return keys;
      };

      expandedKeys.value = getFirstBranchKeys(treeData.value);

      // 默认选中第一条叶子节点
      const getFirstLeafKey = (nodes: any[]): string | null => {
        for (const node of nodes) {
          if (!node.children || node.children.length === 0) {
            return node.key;
          }
          const leafKey = getFirstLeafKey(node.children);
          if (leafKey) return leafKey;
        }
        return null;
      };

      const firstLeafKey = getFirstLeafKey(treeData.value);
      if (firstLeafKey) {
        // 设置默认勾选，并添加所有父节点
        checkedKeys.value = [firstLeafKey];
        addParentKeys(firstLeafKey); // 添加父节点

        // 默认勾选后，需要手动添加视频
        if (monitorType.value === "live") {
          // 查找对应的节点数据
          const findNodeByKey = (nodes: any[], key: string): any => {
            for (const node of nodes) {
              if (node.key === key) return node;
              if (node.children && node.children.length > 0) {
                const found = findNodeByKey(node.children, key);
                if (found) return found;
              }
            }
            return null;
          };

          const firstLeafNode = findNodeByKey(treeData.value, firstLeafKey);
          if (firstLeafNode) {
            const videoUrl =
              firstLeafNode.url || firstLeafNode.videoUrl || firstLeafNode.playUrl;
            if (videoUrl) {
              addVideo({
                flnm: firstLeafNode.name,
                stnm: firstLeafNode.stnm,
                url: videoUrl,
                ...firstLeafNode,
              });
            }
          }
        }
      }
    }
  } catch (error) {
    // 静默处理错误
  } finally {
    treeLoading.value = false;
  }
};

// Tab切换处理
const handleTabChange = (key: string) => {
  activeTab.value = key;
  initTree();
};

// 状态筛选变化时重新加载树
watch(statusFilter, () => {
  initTree();
});

// 监控类型切换处理
const handleMonitorTypeChange = () => {
  // 切换到录像模式时，设置viewLayout为4，隐藏1宫格
  if (monitorType.value === "record") {
    viewLayout.value = "4";
    // 清空中间视频
    videoList.value = Array(9).fill(null);
    checkedKeys.value = [];
  }

  // 切换到实时视频时，恢复在线默认状态
  if (monitorType.value === "live") {
    statusFilter.value = "online";
    // 如果当前是1宫格，保持不变；否则设置为4
    if (!["4", "6", "9"].includes(viewLayout.value)) {
      viewLayout.value = "4";
    }
  }

  // 清空搜索
  searchText.value = "";
  // 重新加载树
  initTree();
};

// 树节点勾选处理
const handleTreeSelect = (checkedKeysValue: any[], info: any) => {
  // 只在实时视频模式下响应勾选
  if (monitorType.value !== "live") return;

  const nodeData = info.node;

  // 判断是勾选还是取消勾选
  const isChecked = checkedKeysValue.includes(nodeData.key);

  if (isChecked) {
    // 勾选：添加视频
    if (!nodeData.children || nodeData.children.length === 0) {
      // 叶子节点：直接添加（需检查数量限制）
      const videoUrl = nodeData.url || nodeData.videoUrl || nodeData.playUrl;
      if (videoUrl) {
        // 检查是否超出布局限制
        const currentVideoCount = videoList.value.filter(
          (v, i) => i < parseInt(viewLayout.value) && v !== null
        ).length;
        const maxCount = parseInt(viewLayout.value);

        if (currentVideoCount < maxCount) {
          addVideo({
            flnm: nodeData.name,
            stnm: nodeData.stnm,
            url: videoUrl,
            ...nodeData,
          });

          // 自动添加所有父节点到 checkedKeys
          addParentKeys(nodeData.key);
        } else {
          // 超出限制，使用 setTimeout 延迟取消勾选，避免与 Tree 组件的自动勾选冲突
          setTimeout(() => {
            // 使用 filter 创建新数组以触发响应式更新
            checkedKeys.value = checkedKeys.value.filter((key) => key !== nodeData.key);
          }, 50);
        }
      } else {
      }
    } else {
      // 父节点：递归查找所有叶子节点并添加视频（需检查数量限制）
      addVideosFromNodeWithLimit(nodeData);
    }
  } else {
    // 取消勾选：移除视频
    if (!nodeData.children || nodeData.children.length === 0) {
      // 叶子节点：直接移除
      removeVideoByNodeKey(nodeData.key);

      // 检查并移除不再需要的父节点
      removeUnnecessaryParentKeys(nodeData.key);
    } else {
      // 父节点：递归查找所有叶子节点并移除视频
      removeVideosFromNode(nodeData);
    }
  }
};

// 添加节点的所有父节点到 checkedKeys（只有当父节点下所有子节点都被勾选时才添加）
const addParentKeys = (childKey: string) => {
  const parentKeys = getParentKeys(childKey);

  parentKeys.forEach((parentKey) => {
    // 查找父节点
    const findNode = (nodes: any[], key: string): any => {
      for (const node of nodes) {
        if (node.key === key) return node;
        if (node.children && node.children.length > 0) {
          const found = findNode(node.children, key);
          if (found) return found;
        }
      }
      return null;
    };

    const parentNode = findNode(treeData.value, parentKey);
    if (parentNode) {
      // 检查父节点下的所有子节点是否都被勾选
      const allChildrenChecked = areAllChildrenChecked(parentNode);
      if (allChildrenChecked && !checkedKeys.value.includes(parentKey)) {
        // 所有子节点都被勾选，添加父节点
        checkedKeys.value = [...checkedKeys.value, parentKey];
      }
    }
  });
};

// 获取节点的所有父节点 key
const getParentKeys = (childKey: string): string[] => {
  const parentKeys: string[] = [];

  const findParents = (
    nodes: any[],
    targetKey: string,
    parents: string[] = []
  ): boolean => {
    for (const node of nodes) {
      if (node.key === targetKey) {
        parentKeys.push(...parents);
        return true;
      }
      if (node.children && node.children.length > 0) {
        if (findParents(node.children, targetKey, [...parents, node.key])) {
          return true;
        }
      }
    }
    return false;
  };

  findParents(treeData.value, childKey);
  return parentKeys;
};

// 检查并移除不再需要的父节点
const removeUnnecessaryParentKeys = (childKey: string) => {
  const parentKeys = getParentKeys(childKey);

  parentKeys.forEach((parentKey) => {
    // 查找父节点
    const findNode = (nodes: any[], key: string): any => {
      for (const node of nodes) {
        if (node.key === key) return node;
        if (node.children && node.children.length > 0) {
          const found = findNode(node.children, key);
          if (found) return found;
        }
      }
      return null;
    };

    const parentNode = findNode(treeData.value, parentKey);
    if (parentNode && checkedKeys.value.includes(parentKey)) {
      // 检查父节点下是否所有直接子节点都被勾选
      const allDirectChildrenChecked = areAllDirectChildrenChecked(parentNode);

      if (!allDirectChildrenChecked) {
        // 不是所有直接子节点都被勾选，移除父节点
        checkedKeys.value = checkedKeys.value.filter((key) => key !== parentKey);

        // 递归检查父节点的父节点
        removeUnnecessaryParentKeys(parentKey);
      }
    }
  });
};

// 检查父节点下是否所有直接子节点都被勾选
const areAllDirectChildrenChecked = (parentNode: any): boolean => {
  if (!parentNode.children || parentNode.children.length === 0) {
    return false;
  }

  // 检查所有直接子节点是否都在 checkedKeys 中
  return parentNode.children.every((child: any) => checkedKeys.value.includes(child.key));
};

// 检查父节点下的所有子节点是否都被勾选
const areAllChildrenChecked = (parentNode: any): boolean => {
  if (!parentNode.children || parentNode.children.length === 0) {
    return false;
  }

  // 获取所有叶子节点的 key
  const getLeafKeys = (node: any): string[] => {
    let keys: string[] = [];
    if (!node.children || node.children.length === 0) {
      return [node.key];
    }
    node.children.forEach((child: any) => {
      keys = keys.concat(getLeafKeys(child));
    });
    return keys;
  };

  const allLeafKeys = getLeafKeys(parentNode);

  // 检查是否所有叶子节点都在 checkedKeys 中
  return allLeafKeys.every((key: string) => checkedKeys.value.includes(key));
};

// 递归添加节点及其所有子节点的视频（带数量限制）
const addVideosFromNodeWithLimit = (node: any) => {
  const maxCount = parseInt(viewLayout.value);

  // 先移除父节点本身的 key（因为我们只关心子节点）
  checkedKeys.value = checkedKeys.value.filter((key) => key !== node.key);

  // 获取当前已添加的视频数量
  const getCurrentVideoCount = () => {
    return videoList.value.filter((v, i) => i < maxCount && v !== null).length;
  };

  // 收集所有叶子节点
  const collectLeafNodes = (n: any): any[] => {
    let leaves: any[] = [];
    if (!n.children || n.children.length === 0) {
      const videoUrl = n.url || n.videoUrl || n.playUrl;
      if (videoUrl) {
        leaves.push(n);
      }
    } else {
      n.children.forEach((child: any) => {
        leaves = leaves.concat(collectLeafNodes(child));
      });
    }
    return leaves;
  };

  const allLeafNodes = collectLeafNodes(node);
  const currentCount = getCurrentVideoCount();
  const remainingSlots = maxCount - currentCount;

  if (remainingSlots <= 0) {
    // 没有剩余位置，延迟取消所有相关节点的勾选
    setTimeout(() => {
      cancelNodeCheck(node);
    }, 100);
    return;
  }

  // 只添加前 remainingSlots 个叶子节点
  const nodesToAdd = allLeafNodes.slice(0, remainingSlots);
  const nodesToCancel = allLeafNodes.slice(remainingSlots);

  // 添加允许的视频并勾选对应节点
  nodesToAdd.forEach((leafNode: any) => {
    addVideo({
      flnm: leafNode.name,
      stnm: leafNode.stnm,
      url: leafNode.url || leafNode.videoUrl || leafNode.playUrl,
      ...leafNode,
    });

    // 将子节点 key 添加到 checkedKeys（不添加父节点）
    if (!checkedKeys.value.includes(leafNode.key)) {
      checkedKeys.value = [...checkedKeys.value, leafNode.key];
    }
  });

  // 先取消超出限制的节点的勾选
  if (nodesToCancel.length > 0) {
    setTimeout(() => {
      cancelNodesCheck(nodesToCancel);

      // 取消后再为所有添加的子节点添加父节点
      nodesToAdd.forEach((leafNode: any) => {
        addParentKeys(leafNode.key);
      });
    }, 50);
  } else {
    // 没有超出限制，直接添加父节点
    setTimeout(() => {
      nodesToAdd.forEach((leafNode: any) => {
        addParentKeys(leafNode.key);
      });
    }, 50);
  }
};

// 取消单个节点的勾选
const cancelNodeCheck = (node: any) => {
  // 使用 filter 创建新数组以触发响应式更新
  checkedKeys.value = checkedKeys.value.filter((key) => key !== node.key);
};

// 取消多个节点的勾选
const cancelNodesCheck = (nodes: any[]) => {
  nodes.forEach((node: any) => {
    cancelNodeCheck(node);
  });
};

// 递归移除节点及其所有子节点的视频
const removeVideosFromNode = (node: any) => {
  if (!node.children || node.children.length === 0) {
    // 叶子节点：移除视频
    removeVideoByNodeKey(node.key);
  } else {
    // 有子节点：递归处理所有子节点
    node.children.forEach((child: any) => {
      removeVideosFromNode(child);
    });
  }
};

// 根据节点key移除视频
const removeVideoByNodeKey = (nodeKey: string) => {
  const index = videoList.value.findIndex((video) => video && video.key === nodeKey);
  if (index !== -1) {
    videoList.value[index] = null;
  }
};

// 监听选中节点、日期范围和监控类型变化，加载录像列表
watch(
  [checkedKeys, dateRange, monitorType],
  ([newCheckedKeys, newDateRange, newMonitorType]) => {
    if (newMonitorType === "record") {
      loadRecordList();
    } else {
      recordList.value = [];
    }
  }
);

// 监听搜索文本变化，实时过滤
watch(searchText, (newValue) => {
  filterTree(newValue);
});

// 过滤树形数据
const filterTree = (keyword: string) => {
  if (!keyword || keyword.trim() === "") {
    // 清空搜索时恢复原始数据
    treeData.value = JSON.parse(JSON.stringify(originalTreeData.value));

    // 重新展开第一条
    const getFirstBranchKeys = (nodes: any[]): string[] => {
      let keys: string[] = [];
      if (nodes.length > 0) {
        const firstNode = nodes[0];
        if (firstNode.children && firstNode.children.length > 0) {
          keys.push(firstNode.key);
          keys = keys.concat(getFirstBranchKeys(firstNode.children));
        }
      }
      return keys;
    };
    expandedKeys.value = getFirstBranchKeys(treeData.value);
    return;
  }

  const lowerKeyword = keyword.toLowerCase();

  // 递归过滤树节点
  const filterNodes = (nodes: any[]): any[] => {
    const filtered: any[] = [];

    nodes.forEach((node) => {
      const nodeName = (node.name || "").toLowerCase();
      const hasChildren = node.children && node.children.length > 0;

      if (hasChildren) {
        // 如果有子节点，先过滤子节点
        const filteredChildren = filterNodes(node.children);

        // 如果父节点名称匹配或子节点有匹配项，则保留该节点
        if (nodeName.includes(lowerKeyword) || filteredChildren.length > 0) {
          filtered.push({
            ...node,
            children: filteredChildren.length > 0 ? filteredChildren : node.children,
          });
        }
      } else {
        // 叶子节点，直接判断是否匹配
        if (nodeName.includes(lowerKeyword)) {
          filtered.push({ ...node });
        }
      }
    });

    return filtered;
  };

  treeData.value = filterNodes(originalTreeData.value);

  // 搜索时展开所有匹配的节点
  const getAllKeys = (nodes: any[]): string[] => {
    let keys: string[] = [];
    nodes.forEach((node) => {
      if (node.children && node.children.length > 0) {
        keys.push(node.key);
        keys = keys.concat(getAllKeys(node.children));
      }
    });
    return keys;
  };

  expandedKeys.value = getAllKeys(treeData.value);
};

onMounted(() => {
  init();
});
</script>

<style scoped lang="scss">
.shiPinJianKongZhuanTi-page {
  position: fixed;
  left: 0;
  top: 60px;
  z-index: 900;
  pointer-events: all;
  width: 100%;
  height: 100%;
  padding-top: 2px;
  background-color: #ffffff;
  box-sizing: border-box;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.custom-tabs {
  width: 100%;
  height: 48px;
  background-color: #ffffff;
  z-index: 6666;

  :deep(.ant-tabs-nav) {
    height: 38px;
    margin-bottom: 0;
    padding-left: 10px;

    .ant-tabs-tab {
      padding: 12px 0;
    }

    .ant-tabs-ink-bar {
      background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAFCAYAAACXU8ZrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMS8wMy8yMrqNQAoAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOklEQVQImWNgQAchkx3QhZhQeEFTExj+MexnCJoyH1mYEUUBwz8kScYFDOtyEhGKMBSgKmTErQChEAA6FRM7O0rIOgAAAABJRU5ErkJggg==")
        no-repeat center bottom;
      border-bottom: 2px solid #005293;
      height: 7px;
    }

    .ant-tabs-tab-active {
      .ant-tabs-tab-btn {
        color: #2f6b98 !important;
      }
    }
  }
}

.tabs-content {
  height: calc(100% - 114px);
  background-color: #ffffff;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 16px 26px 16px;
}

// 顶部标题和图标选择区域
.content-header {
  width: 100%;
  height: 42px;
  line-height: 42px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: #fff;
  border: 1px solid #f0f0f0;

  .header-left {
    width: 300px;
    height: 42px;
    padding: 0 12px;
    border-right: 1px solid #f0f0f0;
    .title {
      font-size: 16px;
      font-weight: 600;
      color: rgba(0, 0, 0, 0.85);
      :deep(.ant-divider) {
        margin-right: 4px;
        height: 1.3em !important;
        border-left: 3px solid rgb(47, 107, 152) !important;
      }
    }
  }

  .header-right {
    height: 42px;
    display: flex;
    align-items: center;
    margin-right: 12px;
    :deep(.ant-radio-group) {
      width: 100%;
      margin-top: 1px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-radius: 0px;
      gap: 8px;
      .ant-radio-button-wrapper {
        width: 28px;
        height: 28px;
        padding: 0 !important;
        border: none !important;
        padding-left: 6px !important;
        border-radius: 0px;
        &::before {
          width: 0px;
        }
        .anticon {
          font-size: 16px;
        }
      }
    }
  }
}

// 主体内容区域
.content-body {
  flex: 1;
  display: flex;
  overflow: hidden;
}

// 左侧面板
.left-panel {
  width: 300px;
  background-color: #fff;
  border-left: 1px solid #f0f0f0;
  border-right: 1px solid #f0f0f0;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  padding: 12px;

  .monitor-radio {
    margin-bottom: 8px;

    :deep(.ant-radio-group) {
      width: 100%;

      .ant-radio-button-wrapper {
        width: 50%;
        height: 32px;
        line-height: 32px;
        text-align: center;
      }
    }
  }

  .search-bar {
    display: flex;
    gap: 4px;

    :deep(.ant-input-wrapper) {
      input {
        height: 30px;
        padding-left: 4px;
      }
      .ant-input-group-addon button {
        width: 32px;
        height: 32px;
      }
    }

    .status-filter {
      flex-shrink: 0;
      display: flex;
      gap: 4px;

      .status-btn {
        width: 32px;
        height: 32px;
        position: relative;
        display: flex;
        justify-content: center;
        align-items: center;
        gap: 4px;
        padding: 4px 6px;
        background-color: #fff;
        border: 1px solid #d9d9d9;
        border-radius: 3px;
        cursor: pointer;
        transition: all 0.2s;
        font-size: 13px;

        .iconfont {
          font-size: 16px;
          color: #8c8c8c;
        }

        .iconfont.__online {
          color: rgb(0, 160, 80);
        }

        &.active {
          background-color: #fff;
          border-color: rgb(47, 107, 152) !important;

          .iconfont:not(.__online) {
            color: #595959;
          }

          &::after {
            content: "";
            position: absolute;
            bottom: -3px;
            right: 0px;
            width: 15px;
            height: 15px;
            background-image: url(@/assets/icons/fishxz.7410ec88.svg);
            background-size: contain;
            background-repeat: no-repeat;
          }
        }
      }
    }
  }

  .tree-container {
    flex: 1;
    overflow-y: auto;

    .tree-spin {
      display: block;
      height: 100%;
      min-height: 100%;
      :deep(.ant-spin-container) {
        height: 100%;
        min-height: 100%;
      }
    }

    .empty-tree {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100%;
      min-height: 100%;
      color: red;
    }

    :deep(.ant-tree) {
      .ant-tree-node-content-wrapper {
        &:hover {
          background-color: #f5f5f5;
        }
      }
      .ant-tree-indent-unit {
        width: 8px;
      }
      .ant-tree-node-selected {
        .ant-tree-node-content-wrapper {
          background-color: #e6f7ff;
        }
      }

      // 下拉箭头样式
      .ant-tree-switcher {
        line-height: 18px;
      }
      .ant-tree-checkbox {
        margin-top: 0;
      }

      .tree-status-icon {
        margin-right: 4px;
        font-size: 14px;

        &.__online {
          color: rgb(0, 160, 80);
        }

        &.offline {
          color: rgb(141, 141, 141);
        }
      }
    }
  }
}

// 中间视频区域
.center-panel {
  flex: 1;
  padding: 20px 12px;
  overflow: hidden;
  border-right: 1px solid #f0f0f0;
  border-bottom: 1px solid #f0f0f0;

  .video-grid {
    display: grid;
    gap: 15px;
    height: 100%;
    grid-auto-rows: 1fr;

    &.layout-1 {
      grid-template-columns: 1fr;
      grid-template-rows: 1fr;
    }

    &.layout-4 {
      grid-template-columns: repeat(2, 1fr);
      grid-template-rows: repeat(2, 1fr);
    }

    &.layout-6 {
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(2, 1fr);
    }

    &.layout-9 {
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(3, 1fr);
    }
  }

  .video-item {
    background-color: #000;
    overflow: hidden;
    min-height: 0;

    .video-placeholder {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      color: #666;

      .video-icon {
        font-size: 48px;
        margin-bottom: 8px;
        opacity: 0.5;
      }

      .video-label {
        font-size: 14px;
        color: #999;
      }
    }
  }
}

// 右侧回放面板
.right-panel {
  width: 280px;
  background-color: #fff;
  border-right: 1px solid #f0f0f0;
  border-bottom: 1px solid #f0f0f0;
  display: flex;
  flex-direction: column;
  flex-shrink: 0;

  .replay-header {
    padding: 8px;
    border-bottom: 1px solid #f0f0f0;

    .replay-title {
      font-size: 16px;
      font-weight: 600;
      color: rgba(0, 0, 0, 0.85);
      :deep(.ant-divider) {
        margin-right: 6px;
        height: 1.2em !important;
        border-left: 3px solid rgb(47, 107, 152) !important;
      }
    }
  }
  .date-picker {
    padding: 12px;
  }

  .record-list {
    flex: 1;
    overflow-y: auto;
    padding: 0 8px 18px;
    .record-spin {
      display: block;
      height: 100%;
      min-height: 100%;
      overflow: hidden;
      overflow-y: auto;
      :deep(.ant-spin-container) {
        height: 100%;
        min-height: 100%;
      }
    }

    .empty-record {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100%;
      min-height: 100%;
    }

    .record-items {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }

    .record-item {
      padding: 0 6px;
      position: relative;
      transition: background-color 0.2s;
      cursor: pointer;

      &:hover {
        background-color: #f5f5f5;

        .sp_btn {
          opacity: 1;
        }
      }

      .record-image-wrapper {
        width: 100%;
        height: 134px;
        border: 1px solid #d9d9d9;
        border-bottom: none;
        padding: 6px;
        overflow: hidden;
        display: flex;
        align-items: center;
        justify-content: center;

        :deep(.ant-image) {
          width: 100%;
          height: 100%;

          img {
            width: 100%;
            height: 100%;
            object-fit: contain;
          }
        }
      }
      .sp_btn {
        opacity: 0.65;
        position: absolute;
        width: 40px;
        height: 40px;
        border-radius: 40px;
        top: 50%;
        left: 50%;
        margin-left: -20px;
        margin-top: -40px;
        background-color: rgb(12, 51, 88);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        i {
          color: #ffffff;
        }
      }

      .record-info {
        height: 50px;
        text-align: center;
        border: 1px solid #d9d9d9;
        border-top: none;
        flex: 1;
        min-width: 0;
        font-size: 14px;

        .record-name {
          padding: 0 8px;
          font-size: 14px;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }

        .record-time {
          font-size: 14px;
        }
      }
    }
  }
}
</style>
