<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="名称" prop="name">
              <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>

    <el-card shadow="hover">
      <template #header>
        <el-row :gutter="10">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd()">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">展开/折叠</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Refresh" @click="handleSyncMountedDevices">更新设备</el-button>
          </el-col>
          <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar>
        </el-row>
      </template>

      <el-table
        ref="lineTableRef"
        v-loading="loading"
        :data="lineList"
        row-key="id"
        border
        :tree-props="{ children: 'children' }"
        :default-expand-all="isExpandAll"
      >
        <el-table-column prop="name" label="名称" min-width="220" />
        <el-table-column prop="level" label="层级" align="center" width="90" />
        <el-table-column prop="pid" label="父级ID" align="center" width="180" />
        <el-table-column label="节点类型" align="center" width="110">
          <template #default="scope">
            <el-tag v-if="scope.row.isDevice === '1'" type="success">设备</el-tag>
            <el-tag v-else-if="scope.row.isDeviceGroup === '1'" type="warning">设备组</el-tag>
            <el-tag v-else>普通</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="类型" align="center" width="110">
          <template #default="scope">
            <dict-tag :options="device_type" :value="scope.row.deviceType" />
          </template>
        </el-table-column>
        <el-table-column prop="deviceId" label="设备ID" min-width="120" />
        <el-table-column prop="deviceGroupId" label="设备组ID" min-width="120" />
        <el-table-column label="创建时间" align="center" prop="createTime" width="180">
          <template #default="scope">
            <span>{{ proxy?.parseTime(scope.row.createTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="修改时间" align="center" prop="updateTime" width="180">
          <template #default="scope">
            <span>{{ proxy?.parseTime(scope.row.updateTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column fixed="right" align="center" label="操作" width="210">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button v-if="canOperate(scope.row)" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
            </el-tooltip>
            <el-tooltip content="新增子级" placement="top">
              <el-button v-if="canAddNormal(scope.row)" link type="primary" icon="Plus" @click="handleAdd(scope.row)" />
            </el-tooltip>
            <el-tooltip content="挂载设备" placement="top">
              <el-button v-if="canMount(scope.row)" link type="primary" icon="Connection" @click="handleMount(scope.row)" />
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button v-if="canOperate(scope.row)" link type="primary" icon="Delete" @click="handleDelete(scope.row)" />
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-body width="640px">
      <el-form ref="lineFormRef" :model="form" :rules="rules" label-width="90px">
        <el-form-item label="上级线路" prop="pid">
          <el-tree-select
            v-model="form.pid"
            :data="lineOptions"
            :props="{ value: 'id', label: 'name', children: 'children' } as any"
            value-key="id"
            placeholder="请选择上级线路"
            check-strictly
            clearable
          />
        </el-form-item>
        <el-form-item label="名称" prop="name">
          <el-input v-model="form.name" placeholder="请输入名称" />
        </el-form-item>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="类型" prop="deviceType">
              <el-select v-model="form.deviceType" placeholder="请选择类型" clearable>
                <el-option v-for="dict in device_type" :key="dict.value" :label="dict.label" :value="dict.value" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="设备ID" prop="deviceId">
              <el-input v-model="form.deviceId" placeholder="普通节点可为空" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="设备组ID" prop="deviceGroupId">
              <el-input v-model="form.deviceGroupId" placeholder="普通节点可为空" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="节点属性">
              <el-checkbox v-model="form.isDevice" true-label="1" false-label="0">设备</el-checkbox>
              <el-checkbox v-model="form.isDeviceGroup" true-label="1" false-label="0">设备组</el-checkbox>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预留5" prop="reserve5">
              <el-input v-model="form.reserve5" placeholder="请输入预留字段5" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog v-model="mountDialog.visible" title="挂载设备" destroy-on-close append-to-body width="520px">
      <el-form ref="mountFormRef" :model="mountForm" label-width="100px">
        <el-form-item label="计量设备" required>
          <el-tree-select
            v-model="selectedMeasuringDeviceId"
            :data="measuringDeviceTreeOptions"
            :props="{ value: 'id', label: 'label', children: 'children' } as any"
            value-key="id"
            placeholder="请选择计量设备"
            check-strictly
            clearable
            filterable
            @change="handleMeasuringDeviceChange"
          />
        </el-form-item>
        <el-form-item label="节点类型">
          <el-tag v-if="mountForm.isDeviceGroup === '1'" type="warning">设备组</el-tag>
          <el-tag v-else-if="selectedMeasuringDeviceId" type="success">设备</el-tag>
          <span v-else>-</span>
        </el-form-item>
        <el-form-item label="名称">
          <el-input v-model="mountForm.name" disabled />
        </el-form-item>
        <el-form-item label="类型">
          <dict-tag v-if="mountForm.deviceType !== undefined && mountForm.deviceType !== ''" :options="device_type" :value="mountForm.deviceType" />
          <span v-else>-</span>
        </el-form-item>
        <el-form-item v-if="mountForm.isDeviceGroup !== '1'" label="设备ID">
          <el-input v-model="mountForm.deviceId" disabled />
        </el-form-item>
        <el-form-item v-else label="设备组ID">
          <el-input v-model="mountForm.deviceGroupId" disabled />
        </el-form-item>
        <el-form-item v-if="mountForm.isDeviceGroup === '1'" label="下级设备">
          <el-table border :data="selectedGroupChildren" empty-text="暂无下级设备" max-height="260">
            <el-table-column label="名称" prop="deviceName" min-width="130" show-overflow-tooltip />
            <el-table-column label="编号" prop="deviceCode" min-width="110" show-overflow-tooltip />
            <el-table-column label="设备ID" prop="deviceId" min-width="110" />
            <el-table-column label="节点类型" align="center" width="90">
              <template #default="scope">
                <el-tag v-if="scope.row.isDeviceGroup === '1'" type="warning">设备组</el-tag>
                <el-tag v-else type="success">设备</el-tag>
              </template>
            </el-table-column>
          </el-table>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitMountForm">确 定</el-button>
          <el-button @click="mountDialog.visible = false">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="LineInfo" lang="ts">
import { addLineInfo, delLineInfo, getLineInfo, listLineInfo, mountLineDevice, syncLineMountedDevices, updateLineInfo } from '@/api/system/line';
import { LineInfoForm, LineInfoQuery, LineInfoVO } from '@/api/system/line/types';
import { listMeasuringDevice } from '@/api/ems/measuringDevice';
import { MeasuringDeviceVO } from '@/api/ems/measuringDevice/types';

const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { device_type } = toRefs<any>(proxy?.useDict('device_type'));

const lineList = ref<LineInfoVO[]>([]);
const lineOptions = ref<LineInfoVO[]>([]);
const loading = ref(false);
const showSearch = ref(true);
const isExpandAll = ref(false);
const selectedMeasuringDeviceId = ref<string | number>();
const measuringDeviceOptions = ref<MeasuringDeviceVO[]>([]);
const measuringDeviceTreeOptions = ref<any[]>([]);

const lineTableRef = ref<ElTableInstance>();
const queryFormRef = ref<ElFormInstance>();
const lineFormRef = ref<ElFormInstance>();
const mountFormRef = ref<ElFormInstance>();

const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const mountDialog = reactive<DialogOption>({
  visible: false,
  title: '挂载设备'
});

const initFormData: LineInfoForm = {
  id: undefined,
  pid: '0',
  name: '',
  isDevice: '0',
  deviceId: '',
  isDeviceGroup: '0',
  deviceGroupId: '',
  deviceType: undefined,
  reserve5: ''
};
const mountForm = ref<LineInfoForm>({
  pid: '0',
  name: '',
  isDevice: '1',
  deviceId: '',
  isDeviceGroup: '0',
  deviceGroupId: '',
  deviceType: undefined
});

const data = reactive<PageData<LineInfoForm, LineInfoQuery>>({
  form: { ...initFormData },
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    name: ''
  },
  rules: {
    name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
  }
});
const { queryParams, form, rules } = toRefs(data);
const selectedMeasuringDevice = computed(() =>
  measuringDeviceOptions.value.find((item) => String(item.id) === String(selectedMeasuringDeviceId.value))
);
const selectedGroupChildren = computed(() => selectedMeasuringDevice.value?.childDevices || []);

const getList = async () => {
  loading.value = true;
  try {
    const res = await listLineInfo(queryParams.value);
    lineList.value = res.rows || [];
    lineOptions.value = [
      {
        ...initFormData,
        id: '0',
        pid: '0',
        name: '顶级',
        level: 0,
        children: lineList.value
      } as LineInfoVO
    ];
  } finally {
    loading.value = false;
  }
};

const reset = () => {
  form.value = { ...initFormData };
  lineFormRef.value?.resetFields();
};

const cancel = () => {
  reset();
  dialog.visible = false;
};

const handleQuery = () => {
  getList();
};

const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
};

const handleToggleExpandAll = () => {
  isExpandAll.value = !isExpandAll.value;
  toggleExpandAll(lineList.value, isExpandAll.value);
};

const toggleExpandAll = (rows: LineInfoVO[], status: boolean) => {
  rows.forEach((row) => {
    lineTableRef.value?.toggleRowExpansion(row, status);
    if (row.children?.length) toggleExpandAll(row.children, status);
  });
};

const handleAdd = (row?: LineInfoVO) => {
  if (row && !canAddNormal(row)) {
    proxy?.$modal.msgError('该节点下不能新增普通节点');
    return;
  }
  reset();
  form.value.pid = row?.id || '0';
  form.value.isDevice = '0';
  form.value.isDeviceGroup = '0';
  dialog.visible = true;
  dialog.title = row?.id ? '新增子级' : '新增线路';
};

const handleUpdate = async (row: LineInfoVO) => {
  reset();
  const res = await getLineInfo(row.id);
  form.value = { ...initFormData, ...res.data };
  dialog.visible = true;
  dialog.title = '修改线路';
};

const isAutoMounted = (row: LineInfoVO) => row.reserve5 === 'auto_mounted';
const canOperate = (row: LineInfoVO) => row.source !== 'measuringDevice' && !isAutoMounted(row);
const canAddNormal = (row: LineInfoVO) => canOperate(row) && row.isDevice !== '1' && row.isDeviceGroup !== '1';
const canMount = (row: LineInfoVO) => canOperate(row) && row.isDevice !== '1' && row.isDeviceGroup !== '1';

const loadMeasuringDevices = async () => {
  const res = await listMeasuringDevice({ pageNum: 1, pageSize: 10000 });
  measuringDeviceOptions.value = res.rows || [];
  measuringDeviceTreeOptions.value = buildMeasuringDeviceTree(measuringDeviceOptions.value);
};

const formatMeasuringDeviceLabel = (item: MeasuringDeviceVO) => {
  const nodeType = item.isDeviceGroup === '1' ? '设备组' : '设备';
  return `${item.deviceName || item.deviceId || item.deviceCode || ''}${item.deviceCode ? ` / ${item.deviceCode}` : ''}${item.deviceId ? ` / ${item.deviceId}` : ''} / ${nodeType}`;
};

const buildMeasuringDeviceTree = (rows: MeasuringDeviceVO[]) => {
  const map = new Map<string, any>();
  const roots: any[] = [];
  rows.forEach((row) => {
    map.set(String(row.id), {
      id: row.id,
      label: formatMeasuringDeviceLabel(row),
      children: [],
      raw: row
    });
  });
  map.forEach((node) => {
    const parentId = node.raw.parentDeviceGroupId === undefined || node.raw.parentDeviceGroupId === null ? '' : String(node.raw.parentDeviceGroupId);
    const parent = parentId ? map.get(parentId) : undefined;
    if (parent) parent.children.push(node);
    else roots.push(node);
  });
  const sortRows = (items: any[]) => {
    items.sort((left, right) => {
      if (left.raw.isDeviceGroup !== right.raw.isDeviceGroup) return left.raw.isDeviceGroup === '1' ? -1 : 1;
      return String(left.raw.deviceName || left.raw.deviceCode || left.raw.deviceId || '').localeCompare(
        String(right.raw.deviceName || right.raw.deviceCode || right.raw.deviceId || ''),
        'zh-CN'
      );
    });
    items.forEach((item) => {
      if (item.children.length) sortRows(item.children);
      else delete item.children;
    });
  };
  sortRows(roots);
  return roots;
};

const handleMeasuringDeviceChange = (id?: string | number) => {
  const selected = measuringDeviceOptions.value.find((item) => String(item.id) === String(id));
  if (!selected) {
    mountForm.value.name = '';
    mountForm.value.deviceType = undefined;
    mountForm.value.deviceId = '';
    mountForm.value.deviceGroupId = '';
    mountForm.value.isDevice = '1';
    mountForm.value.isDeviceGroup = '0';
    return;
  }
  mountForm.value.name = selected.deviceName || selected.deviceCode || selected.deviceId || '';
  mountForm.value.deviceType = selected.deviceType;
  mountForm.value.isDeviceGroup = selected.isDeviceGroup === '1' ? '1' : '0';
  mountForm.value.isDevice = selected.isDeviceGroup === '1' ? '0' : '1';
  mountForm.value.deviceId = selected.isDeviceGroup === '1' ? '' : selected.deviceId || selected.deviceCode || '';
  mountForm.value.deviceGroupId = selected.isDeviceGroup === '1' ? selected.deviceId || selected.deviceCode || String(selected.id) : '';
};

const handleMount = (row: LineInfoVO) => {
  if (!canMount(row)) {
    proxy?.$modal.msgError('设备节点下不可挂载其他节点');
    return;
  }
  mountForm.value = {
    pid: row.id,
    name: '',
    isDevice: '1',
    deviceId: '',
    isDeviceGroup: '0',
    deviceGroupId: '',
    deviceType: undefined
  };
  selectedMeasuringDeviceId.value = undefined;
  loadMeasuringDevices();
  mountDialog.visible = true;
};

const submitMountForm = () => {
  const selected = selectedMeasuringDevice.value;
  if (!selected) {
    proxy?.$modal.msgError('请选择计量设备');
    return;
  }
  const data = {
    ...mountForm.value,
    measuringDeviceId: selected.id,
    isDevice: selected.isDeviceGroup === '1' ? '0' : '1',
    isDeviceGroup: selected.isDeviceGroup === '1' ? '1' : '0',
    deviceId: selected.isDeviceGroup === '1' ? undefined : selected.deviceId,
    deviceGroupId: selected.isDeviceGroup === '1' ? selected.deviceId || selected.deviceCode || String(selected.id) : undefined,
    deviceType: selected.deviceType,
    name: selected.deviceName || selected.deviceCode || selected.deviceId || ''
  };
  mountLineDevice(data).then(async () => {
    proxy?.$modal.msgSuccess('挂载成功');
    mountDialog.visible = false;
    await getList();
  });
};

const handleSyncMountedDevices = async () => {
  await syncLineMountedDevices();
  proxy?.$modal.msgSuccess('设备更新成功');
  await getList();
};

const submitForm = () => {
  lineFormRef.value?.validate(async (valid: boolean) => {
    if (!valid) return;
    if (form.value.id) {
      await updateLineInfo(form.value);
    } else {
      await addLineInfo(form.value);
    }
    proxy?.$modal.msgSuccess('操作成功');
    dialog.visible = false;
    await getList();
  });
};

const handleDelete = async (row: LineInfoVO) => {
  await proxy?.$modal.confirm(`是否确认删除"${row.name}"及其全部下级数据?`);
  await delLineInfo(row.id);
  proxy?.$modal.msgSuccess('删除成功');
  await getList();
};

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