<script setup lang="ts">
import subjectApi from '@/api/subject/subject'
import type { TextBook } from '@/api/subject/subject'
import { debounce } from '@/hooks'
import { ElTree } from 'element-plus'
import { cloneDeep } from 'lodash-es'

const props = withDefaults(
  defineProps<{
    modelValue: boolean
    book: TextBook
    maskClose: boolean
    selectedList?: any[]
  }>(),
  {
    maskClose: true,
    selectedList: [] as any,
  },
)
const emits = defineEmits(['update:modelValue', 'ok'])
const OSS_URL = import.meta.env.VITE_OSS_URL
const arrowUrl = `url(${OSS_URL}/icon/textbook_arrow_up.svg)
        center/contain no-repeat`

const show = computed({
  get() {
    return props.modelValue
  },
  set(newVal) {
    emits('update:modelValue', newVal)
    if (!newVal) {
      originChapterList = undefined
      chapterFilter.value = chapter_filter_all
    }
  },
})

// 筛选章节
const chapter_filter_all = '1'
const chapter_filter_root = '2'
const chapterFilterOptions = [
  {
    label: '显示全部',
    value: chapter_filter_all,
  },
  {
    label: '仅显示根章节',
    value: chapter_filter_root,
  },
]
const chapterFilter = ref(chapter_filter_all)
const showChapterFilter = ref(false)

let lastBookId = undefined as any
let originChapterList = undefined as any

const loading = ref(false)
const chapterList = ref<anyObj[]>([])

const tree = ref<InstanceType<typeof ElTree>>()
const checkAllChecked = ref(false)
const checkAllIndeterminate = ref(false)
function onAllSelect() {
  if (checkAllChecked.value) {
    tree.value?.setCheckedKeys(chapterList.value.map(item => item.id))
  } else {
    tree.value?.setCheckedKeys([])
  }
}

function onCheckChange() {
  const keys = tree.value?.getCheckedKeys(false) as any[]
  let checkCount = 0
  for (const chapter of chapterList.value) {
    if (keys.includes(chapter.id)) {
      checkCount++
    }
  }
  checkAllChecked.value = checkCount === chapterList.value.length
  if (checkAllChecked.value) {
    checkAllIndeterminate.value = false
  } else {
    checkAllIndeterminate.value = keys.length > 0
  }
}

function removeEmptyChildren(items: any[]) {
  if (!items?.length) return
  for (const item of items) {
    if (!item.children?.length) {
      delete item.children
    } else {
      removeEmptyChildren(item.children)
    }
  }
}

function preprocessChapters() {
  removeEmptyChildren(originChapterList)

  // 是否要显示过滤器
  showChapterFilter.value = originChapterList.some((item: any) => item.children?.length)
}

function processChaptersByFilter() {
  if (!originChapterList) return
  if (chapterFilter.value === chapter_filter_all) {
    chapterList.value = cloneDeep(originChapterList)
  } else {
    const newList = cloneDeep(originChapterList)
    for (const chapter of newList) {
      delete chapter.children
    }
    chapterList.value = newList
  }
}

watch(() => chapterFilter.value, processChaptersByFilter)

// 获取章节
async function getChapters() {
  loading.value = true

  setTimeout(async () => {
    let newBook = false
    try {
      const { data: res } = await subjectApi.getSubjectChapterTree({ textBookId: props.book.id })
      originChapterList = res.data
      preprocessChapters()
      processChaptersByFilter()
      newBook = lastBookId !== props.book.id
      lastBookId = props.book.id
    } finally {
      loading.value = false

      await nextTick()
      if (props.selectedList?.length && !newBook) {
        tree.value?.setCheckedKeys(props.selectedList, true)
      } else {
        checkAllChecked.value = false
        checkAllIndeterminate.value = false
        tree.value?.setCheckedKeys([])
      }
    }
  }, 100)
}
const debounceOk = debounce(onOk, 1000)

async function onOpen() {
  getChapters()
}

function selectCheckedChapter(treeChapters: any[], chapters: any[]) {
  for (const chapter of treeChapters) {
    if (!chapter.children?.length) {
      chapters.push(chapter)
    } else {
      if (chapter.size === chapter.children?.length) {
        chapters.push(chapter)
      }
      selectCheckedChapter(chapter.children, chapters)
    }
  }
}

async function onOk() {
  // const chapters = tree.value?.getCheckedNodes(false) as any[]
  // 把半选中的也加进来
  const halfChapters = tree.value?.getCheckedNodes(false, true) as any[]
  const halfChapterMap = {} as any
  const treeChapters = [] as any
  for (const chapter of halfChapters) {
    // 转换成新的章节对象
    const newChapter = {
      id: chapter.id,
      name: chapter.name,
    } as any
    // 设置子节点的数量
    if (chapter.children?.length) {
      newChapter.size = chapter.children.length
    }
    // 存储到map中
    halfChapterMap[chapter.id] = newChapter
    if (chapter.pid === '0' || !chapter.id) {
      // 根节点
      treeChapters.push(newChapter)
    } else {
      // 添加到父节点的children数组中
      const parentChapter = halfChapterMap[chapter.pid]
      let children = parentChapter.children
      if (!children) {
        children = []
        parentChapter.children = children
      }
      children.push(newChapter)
    }
  }

  const chapters = [] as any[]
  selectCheckedChapter(treeChapters, chapters)

  emits('ok', chapters, treeChapters)
}
</script>

<template>
  <el-dialog
    v-model="show"
    class="chapter-list"
    :show-close="false"
    destroy-on-close
    :close-on-click-modal="maskClose && !loading"
    :close-on-press-escape="maskClose && !loading"
    align-center
    v-bind="$attrs"
    @open="onOpen"
  >
    <board-bg class="body">
      <div class="content">
        <div class="tips">
          <LineFont text="选择章节" size="48" space="20" />
          <div class="small-tip">{{ book.clean?.fullName }}</div>
        </div>
        <div class="main">
          <Empty v-if="loading" type="loading" />
          <div v-else class="list">
            <div class="list-head">
              <div class="left">
                <mj-check
                  v-if="chapterList.length"
                  v-model="checkAllChecked"
                  :indeterminate="checkAllIndeterminate"
                  @change="onAllSelect"
                />
                <span>目录</span>
              </div>
              <div class="right">
                <select-tab
                  v-if="showChapterFilter"
                  v-model="chapterFilter"
                  :data-list="chapterFilterOptions"
                  type="small"
                />
              </div>
            </div>
            <el-tree
              ref="tree"
              :data="chapterList"
              show-checkbox
              node-key="id"
              :props="{
                children: 'children',
                label: 'name',
              }"
              @check-change="onCheckChange"
            />
          </div>
        </div>
      </div>
      <div
        v-if="!loading"
        :class="{
          footer: true,
          'is-suspension': true,
        }"
      >
        <mj-button type="warn" width="386" height="108" size="48" @click="debounceOk"
          >确认</mj-button
        >
      </div>
    </board-bg>
  </el-dialog>
</template>

<style lang="scss">
.chapter-list {
  width: 1600px;
  height: 92vh;
  margin: 0;
  padding: 0;
  background: transparent;
  box-shadow: none;

  .el-dialog__header {
    display: none;
  }

  .el-dialog__body {
    height: 100%;
    padding: 0;
    position: relative;

    .body {
      height: 100%;
      .content {
        width: 100%;
        .tips {
          width: 100%;
          height: auto;
          padding: 9.33vh 0 $space-3;
          display: flex;
          flex-wrap: wrap;
          align-items: center;
          justify-content: center;
          font-family: $font-special;
          font-size: $font-size-7;
          color: $font-tag-color;
          .small-tip {
            width: 100%;
            font-family: OPPOSans;
            text-align: center;
            font-size: $font-size-7;
            line-height: 1.5em;
            margin-top: $space-1_h;
          }
        }

        .main {
          height: 64.17vh;
          padding: 0 $space-6;
          .list {
            height: 100%;
            border-radius: 2.5vh;
            background: #fff;

            .list-head {
              width: 100%;
              height: 6.67vh;
              border-radius: 2.5vh 2.5vh 0 0;
              background: #90fcf7;
              color: $font-tag-color;
              font-size: $font-size-7;
              line-height: 1.5em; /* 150% */
              display: flex;
              align-items: center;
              column-gap: 15px;
              padding: 0 80px;
              .x-icon {
                cursor: pointer;
              }
            }
            .el-scrollbar {
              height: 56.67vh;
            }
          }
        }
      }
      .footer {
        text-align: center;
        z-index: 100;
        .x-button {
          margin-right: $space-4;
          &:last-child {
            margin-right: 0;
          }
        }
        &.is-suspension {
          position: absolute;
          bottom: 4.17vh;
          left: 50%;
          transform: translateX(-50%);
        }
      }
    }
  }
}
</style>

<style lang="scss" scoped>
$margin_v: 4vh;
$margin_h: 2.08vh;

@mixin underline {
  position: relative;

  &::after {
    position: absolute;
    bottom: -2.33vh;
    left: 0;
    content: '';
    display: block;
    width: calc(100%);
    height: 0.08vh;
    background: repeating-linear-gradient(
      to right,
      rgba(0, 0, 0, 0.15),
      rgba(0, 0, 0, 0.15) 8px,
      transparent 8px,
      transparent 16px /* 线条间隔 */
    );
  }
}

.list {
  @include checkbox;

  :deep(.el-tree) {
    height: 56.67vh;
    overflow: scroll;
    @include hidden_scroll;
    display: flex;
    flex-direction: column;
    gap: $margin_v;

    .el-tree-node__children {
      margin-top: $margin_v;
      display: flex;
      flex-direction: column;
      gap: $margin_v;
    }

    padding: $margin_h;

    .el-checkbox {
      margin-right: $margin_h;
    }

    .el-tree-node__expand-icon {
      display: inline-block;
      width: 32px;
      height: 2.67vh;
      background: v-bind(arrowUrl);
      transition: all 0.3s ease;
      transform: rotate(0deg);
      margin-right: $margin_h;

      &.is-leaf {
        visibility: hidden;
      }

      &.expanded {
        transform: rotate(180deg);
      }
      svg {
        display: none;
      }
    }

    .el-tree-node {
      .el-tree-node__content {
        // padding: 0.5vh 0;
        display: flex;
        align-items: center;
        @include underline;
      }

      .el-tree-node__label {
        font-size: 2.67vh !important;
      }
    }
  }

  &-head {
    display: flex;
    align-items: center;
    justify-content: space-between;

    .left {
      display: flex;
      align-items: center;
    }
  }
}
</style>
