<template>
  <el-dialog
    :model-value="visible"
    title="选择部门"
    :width="600"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :destroy-on-close="true"
    :append-to-body="true"
    @open="onOpen"
    @close="onClose"
  >
    <div class="selector">
      <div class="selector-left">
        <el-scrollbar>
          <el-tree
            ref="selectorTreeRef"
            :props="treeProps"
            node-key="fullPathName"
            :show-checkbox="true"
            :check-strictly="true"
            :default-checked-keys="selectedKeys"
            :load="onLazyLoad"
            lazy
            @check-change="onCheckChange"
            class="cacp-pd-s"
          >
            <template #default="{ data }">
              <el-icon class="cacp-mr-s" :size="16">
                <Grid />
              </el-icon>
              <span>{{ data.oguName }}</span>
            </template>
          </el-tree>
        </el-scrollbar>
      </div>
      <div class="selector-right">
        <div class="selector-toolbar">
          <span class="count">已选 {{ count }} 个</span><el-link type="primary" @click.prevent="onClear">清空</el-link>
        </div>
        <div class="selector-list">
          <selector-list :dataList="selectedList" @on-delete="onRemove"></selector-list>
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="onClose">取消</el-button>
      <el-button type="primary" @click="onSave">确定</el-button>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import type { ElTree } from 'element-plus'
import type TreeNode from 'element-plus/es/components/tree/src/model/node'
import SelectorList from './SelectorList.vue'
import { cloneDeep } from 'lodash-es'
import * as apis from '@/apis/auth'
import type { CacpOrganization } from '@cacp/ui'
import { SuccessResultCode } from '@cacp/ui'
const selectorTreeRef = ref<InstanceType<typeof ElTree>>()
const props = withDefaults(
  defineProps<{
    visible: boolean
    multiple?: boolean
    value?: Array<CacpOrganization>
    rootPath?: string
  }>(),
  {
    visible: false,
    multiple: false,
    value: () => [],
    rootPath: ''
  }
)
const emits = defineEmits<{
  (e: 'on-close'): void
  (e: 'on-save', value: Array<CacpOrganization>): void
}>()
const treeProps = {
  label: 'oguName'
}
const cachedList = ref<Array<CacpOrganization>>([])
const selectedKeys = ref<Array<string>>([])
const selectedList = computed<Array<CacpOrganization>>(() => {
  return cachedList.value.filter((o) => selectedKeys.value.includes(o.fullPathName))
})
const count = computed<number>(() => {
  return selectedKeys.value.length
})
function onOpen(): void {
  selectedKeys.value = props.value ? props.value.map((o) => o.fullPathName) : []
  cachedList.value = props.value ? cloneDeep(props.value) : []
}

function onClose(): void {
  emits('on-close')
}

function onSave(): void {
  emits('on-save', selectedList.value)
}
async function onLazyLoad(
  node: TreeNode,
  resolve: (data: Array<CacpOrganization>) => void,
  reject: () => void
): Promise<void> {
  if (node.level === 0) {
    let root: CacpOrganization
    if (props.rootPath) {
      const result = await apis.getOrganizationByPath(props.rootPath)
      if (result.code === SuccessResultCode && result.data) {
        root = result.data
        resolve([root])
      } else {
        if (reject) {
          reject()
        }
      }
    } else {
      const result = await apis.getRootOrganization()
      if (result.code === SuccessResultCode && result.data) {
        root = result.data
        resolve([root])
      } else {
        if (reject) {
          reject()
        }
      }
    }
  } else {
    const parent = node.data
    const result = await apis.getOrganizationListByParent(parent.fullPathName, true)
    if (result.code === SuccessResultCode) {
      const children = result.data ?? []
      resolve(children)
    } else {
      if (reject) {
        reject()
      }
    }
  }
}

function onCheckChange(data: CacpOrganization, checked: boolean) {
  if (checked) {
    handleCachedList([data])
    if (!props.multiple) {
      selectedKeys.value.splice(0, 1, data.fullPathName)
    } else {
      if (!selectedKeys.value.includes(data.fullPathName)) {
        selectedKeys.value.push(data.fullPathName)
      }
    }
  } else {
    const idx = selectedKeys.value.indexOf(data.fullPathName)
    if (idx > -1) {
      selectedKeys.value.splice(idx, 1)
    }
  }
  handleCheckStatus()
}

function onRemove(fullPathName: string): void {
  const idx = selectedKeys.value.indexOf(fullPathName)
  if (idx > -1) {
    selectedKeys.value.splice(idx, 1)
  }
  handleCheckStatus()
}

function onClear(): void {
  selectedKeys.value = []
  handleCheckStatus()
}

function handleCachedList(list: Array<CacpOrganization>): void {
  for (const org of list) {
    const idx = cachedList.value.findIndex((o) => o.fullPathName === org.fullPathName)
    if (idx > -1) {
      cachedList.value.splice(idx, 1)
    }
    cachedList.value.push(org)
  }
}

function handleCheckStatus(): void {
  if (selectorTreeRef.value) {
    selectorTreeRef.value.setCheckedKeys(selectedKeys.value, false)
  }
}
</script>

<style lang="less" scoped>
.selector {
  display: flex;
  align-items: flex-start;
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  min-height: 260px;
  max-height: 400px;
  align-items: stretch;
  &-left {
    flex: 1;
    border-right: 1px solid var(--el-border-color);
  }
  &-right {
    flex: 1;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  &-list {
    flex: 1;
    overflow: hidden;
  }
  &-toolbar {
    line-height: 32px;
    height: 32px;
    padding: 0 var(--cacp-padding-space-s);
    font-size: var(--font-size-s);
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--el-border-color);
    justify-content: space-between;
  }
}
</style>
