<template>
  <div class="pool-task-select" :class="{ vertical: layout === 'vertical' }">
    <el-tree-select
      v-if="editable"
      v-model="selectedKeys"
      :data="treeData"
      :disabled="disabled"
      :loading="loading"
      multiple
      show-checkbox
      check-strictly
      filterable
      :filter-node-method="filterNodeFun"
      node-key="value"
      :render-after-expand="false"
      :props="{ label: 'label', children: 'children' }"
      :placeholder="$t('通用.请选择')"
      @check="onCheckFun"
      @remove-tag="removeTagFun"
    >
      <template #default="{ data }">
        <span :class="{ 'pool-root-node': data.value?.startsWith('pool_') }">
          {{ data.label }}
        </span>
      </template>
    </el-tree-select>
    <span v-else class="plain-label">
      <template v-if="totalTaskCount === 1">
        <span class="pool-name"
          >{{ modelValue[0].simulationPoolName }}_{{ modelValue[0].simulationPoolVersion }}</span
        >
        <span v-if="modelValue[0].taskBaseInfoList?.length" class="task-list">
          ({{ modelValue[0].taskBaseInfoList.map((t) => t.taskName).join(', ') }})
        </span>
      </template>
      <template v-else-if="totalTaskCount >= 2">
        <el-popover placement="bottom" trigger="hover" :width="280">
          <template #reference>
            <span class="link-text">{{ $t('工况库.关联N个工况', { count: totalTaskCount }) }}</span>
          </template>
          <div class="pool-list">
            <div v-for="(pool, index) in modelValue" :key="index" class="pool-item">
              <span class="pool-name"
                >{{ pool.simulationPoolName }}_{{ pool.simulationPoolVersion }}</span
              >
              <span v-if="pool.taskBaseInfoList?.length" class="task-list">
                ({{ pool.taskBaseInfoList.map((t) => t.taskName).join(', ') }})
              </span>
            </div>
          </div>
        </el-popover>
      </template>
      <template v-else>--</template>
    </span>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, computed, onMounted } from 'vue';
import { getAllTaskPoolCurrentVersionApi } from '@/api/task/taskpool';

interface TaskBaseInfo {
  taskName: string;
  taskCode: string;
  uuid: string;
  poolName?: string;
  version?: string;
}

interface PoolInfo {
  simulationPoolId?: number;
  simulationPoolName?: string;
  simulationPoolVersion: string;
  simulationPoolTaskIds: string[];
  taskBaseInfoList?: TaskBaseInfo[];
}

interface Props {
  modelValue?: PoolInfo[];
  editable?: boolean;
  layout?: 'horizontal' | 'vertical';
  disabled?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  editable: true,
  layout: 'horizontal',
  disabled: false,
});

const emits = defineEmits(['update:modelValue']);
const selectedKeys = ref<string[]>([]);
const poolTaskData = ref<any[]>([]);
const loading = ref(false);

const queryPoolTaskDataFun = async () => {
  loading.value = true;
  try {
    const res: any = await getAllTaskPoolCurrentVersionApi({});
    if (res.code === 200) {
      poolTaskData.value = (res.data || []).reverse();
    } else {
      poolTaskData.value = [];
    }
  } finally {
    loading.value = false;
  }
};

onMounted(() => {
  if (props.editable) {
    queryPoolTaskDataFun();
  }
});

const convertNodesFun = (nodes: any[], poolId: number, poolVersion: string): any[] => {
  return nodes
    .filter((node) => node.levelType !== 'performance' && node.nodeType !== 'performance')
    .map((node) => {
      const isTask = node.levelType === 'task' || node.nodeType === 'task';
      const result: any = {
        value: node.uuid,
        label: node.nodeName,
        nodeType: node.nodeType,
        levelType: node.levelType,
        poolId,
        poolVersion,
        disabled: !isTask,
      };
      if (node.children?.length) {
        result.children = convertNodesFun(node.children, poolId, poolVersion);
      }
      return result;
    });
};

const totalTaskCount = computed(
  () => props.modelValue?.reduce((sum, p) => sum + (p.taskBaseInfoList?.length || 0), 0) || 0
);

const treeData = computed(() => {
  return poolTaskData.value.map((pool: any) => {
    const { poolBrief, nodes } = pool;
    return {
      value: `pool_${poolBrief.id}`,
      label: `${poolBrief.poolName}_${poolBrief.currentVersion}`,
      poolId: poolBrief.id,
      poolName: poolBrief.poolName,
      poolVersion: poolBrief.currentVersion,
      children: convertNodesFun(nodes, poolBrief.id, poolBrief.currentVersion),
      disabled: true,
    };
  });
});

watch(
  () => props.modelValue,
  (val) => {
    if (val?.length) {
      selectedKeys.value = val.flatMap((item) => item.simulationPoolTaskIds || []);
    } else {
      selectedKeys.value = [];
    }
  },
  { immediate: true, deep: true }
);

const findNodeInTreeFun = (nodes: any[], value: string): any => {
  for (const node of nodes) {
    if (node.value === value) return node;
    if (node.children?.length) {
      const found = findNodeInTreeFun(node.children, value);
      if (found) return found;
    }
  }
  return null;
};

const filterNodeFun = (value: string, data: any) => {
  if (!value) return true;
  return data.label?.toLowerCase().includes(value.toLowerCase());
};

const onCheckFun = () => {
  if (!selectedKeys.value.length) {
    emits('update:modelValue', []);
    return;
  }

  const groupMap = new Map<string, PoolInfo>();
  for (const taskId of selectedKeys.value) {
    for (const pool of treeData.value) {
      const found = findNodeInTreeFun(pool.children || [], taskId);
      if (found) {
        const key = `${pool.poolId}_${pool.poolVersion}`;
        if (!groupMap.has(key)) {
          groupMap.set(key, {
            simulationPoolId: pool.poolId,
            simulationPoolName: pool.poolName,
            simulationPoolVersion: pool.poolVersion,
            simulationPoolTaskIds: [],
          });
        }
        const poolInfo = groupMap.get(key);
        if (poolInfo) {
          poolInfo.simulationPoolTaskIds.push(taskId);
        }
        break;
      }
    }
  }

  emits('update:modelValue', Array.from(groupMap.values()));
};
const removeTagFun = () => {
  onCheckFun();
};
</script>

<style lang="scss" scoped>
.pool-task-select {
  width: 100%;
  &.vertical {
    display: flex;
    flex-direction: column;
  }
}

.pool-root-node {
  font-weight: bold;
}

.plain-label {
  .pool-name {
    font-weight: bold;
  }
  .task-list {
    color: #595959;
    font-size: var(--font-size-text-small);
  }
  .link-text {
    color: var(--el-color-primary);
    cursor: pointer;
    &:hover {
      text-decoration: underline;
    }
  }
}

.pool-list {
  .pool-item {
    padding: 4px 0;
    .pool-name {
      font-weight: bold;
    }
    .task-list {
      color: #595959;
      font-size: var(--font-size-text-small);
    }
  }
}
</style>
