<script setup>
import { ref } from "vue";

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => [],
  },
  options: Array,
  isSingle: {
    type: Boolean,
    default: false,
  },
  required: {
    type: Boolean,
    default: true,
  },
});

const emits = defineEmits(["update:modelValue", "change"]);

const active = computed({
  get() {
    return props.modelValue;
  },
  set(newVal) {
    emits("update:modelValue", newVal);
  },
});

function handleClick(node, nodeIdx, parentNode) {
  if (props.isSingle) {
    // 全局单选
    if (!props.required && active.value[0]?.node.value === node.value) {
      active.value = [{}];
    } else {
      active.value = [
        {
          node,
          parentNode,
        },
      ];
    }
  } else {
    // 分组单选
    if (active.value[nodeIdx].length > 0) {
      if (
        (parentNode.optional && active.value[nodeIdx][0] === node.value) ||
        (!props.required && active.value[nodeIdx][0] === node.value)
      ) {
        active.value[nodeIdx] = [];
      } else {
        active.value[nodeIdx] = [node.value];
      }
    } else {
      active.value[nodeIdx].push(node.value);
    }
  }
  emits("change");
}
</script>

<template>
  <div class="filter-box">
    <div
      class="filter-row"
      v-for="(item, itemIdx) in options"
      :key="item.label"
    >
      <template v-if="item.children && item.children.length">
        <div class="filter-group-label">{{ item.label }}</div>
        <div class="filter-group-child">
          <ul>
            <template v-for="child in item.children" :key="child.value">
              <template v-if="child.children">
                <el-popover
                  placement="bottom-start"
                  :width="200"
                  trigger="hover"
                  :teleported="false"
                  :persistent="false"
                >
                  <template #reference>
                    <li
                      :class="{
                        active: props.isSingle
                          ? child.children.some((i) => i.value === child.value)
                          : child.children.some((i) =>
                              active[itemIdx]?.includes(i.value)
                            ),
                      }"
                    >
                      {{ child.label }}（{{
                        child.children.find((i) =>
                          active[itemIdx]?.includes(i.value)
                        )?.label || "+"
                      }}）
                    </li>
                  </template>
                  <span
                    :class="{
                      option: true,
                      active: props.isSingle
                        ? active.some((i) => i.node.value === option.value)
                        : active[itemIdx]?.includes(option.value),
                    }"
                    v-for="option in child.children"
                    :key="option.value"
                    @click="handleClick(option, itemIdx, item)"
                    >{{ option.label }}</span
                  >
                </el-popover>
              </template>
              <template v-else>
                <li
                  :class="{
                    active: props.isSingle
                      ? active.some((i) => i.node.value === child.value)
                      : active[itemIdx]?.includes(child.value),
                  }"
                  @click="handleClick(child, itemIdx, item)"
                >
                  {{ child.label }}
                </li>
              </template>
            </template>
          </ul>
        </div>
      </template>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.filter-box {
  .filter-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-sizing: border-box;
    line-height: 40px;

    .filter-group-label {
      padding-right: 16px;
      font-weight: bold;
      position: relative;
      flex: 1;
      &::after {
        content: "";
        width: 4px;
        height: 50%;
        display: block;
        background: var(--el-color-primary);
        position: absolute;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
      }
    }
    .filter-group-child {
      width: calc(100% - 60px);
      ul {
        padding: 0;
        margin: 8px;
        list-style-type: none;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        li {
          cursor: pointer;
          padding: 0 16px;
          white-space: nowrap;
          &.active {
            color: var(--el-color-primary);
          }
        }

        :deep(.el-popover) {
          width: auto !important;
          .option {
            cursor: pointer;
            padding: 4px 16px;
            &.active {
              color: var(--el-color-primary);
            }
          }
        }
      }
    }
  }
}
</style>
