<script lang="ts" setup>
import { difference } from 'lodash-es'
import { computed, onMounted, ref, watch } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import { getAllfieldList, getfieldList, savefield } from '@/api/home/filter'
import { useUser } from '@/store/modules/user'

const props = defineProps({
  reviewType: {
    type: Number,
    default: () => 0,
    require: true,
  },
})

const emit = defineEmits<{
  (e: 'commit', columns: any[])
}>()

// 左侧隐藏列表
const offList = ref<any[]>([])
// 右侧显示列表
const fixLeftList = ref<any[]>([])
const onList = ref<any[]>([])
onMounted(async () => {
  const userStore = useUser()
  const userInfo = userStore.getUserInfo
  let res
  res = await getAllfieldList(props.reviewType) // 所有筛选项目
  const allList = res.data
  res = await getfieldList(props.reviewType, userInfo.id) // 当前用户选择的项目
  const useList = res.data
  /**
   * name 标题
   * id 键值
   * fix 是否默认
   * checked 是否选中
   */
  const userFieldFixed = useList.userFieldFixed?.split(',')
  const userFieldUnFixed = useList.userFieldUnFixed?.split(',')
  const mustList: any[] = []
  allList?.forEach((v) => {
    const item = {
      name: v.fieldDesc,
      id: v.name,
      fix: v.isrequired == 2,
      checked:
        v.isrequired == 2
        || Boolean(userFieldFixed?.find(v2 => v2 == v.name))
        || Boolean(userFieldUnFixed?.find(v2 => v2 == v.name)),
    }
    if (item.fix) {
      mustList.push(item)
      if (!userFieldFixed?.length && !userFieldUnFixed?.length)
        fixLeftList.value.push(item)
    }
    if (userFieldFixed?.find(v2 => v2 == v.name))
      fixLeftList.value.push(item)

    if (userFieldUnFixed?.find(v2 => v2 == v.name))
      onList.value.push(item)

    offList.value.push(item)
  })
})

const allCount = computed(() => {
  return `全部字段(共${offList.value.length - 1}个)`
})

const selectCount = computed(() => {
  return `显示字段(共${onList.value.length}个)`
})

const show = ref(false)
const checkAll = ref(false)

function showModal() {
  show.value = true
}

function closeModal() {
  show.value = false
}

async function handleSumbit(e: MouseEvent) {
  e.preventDefault()
  closeModal()
  const userStore = useUser()
  const userInfo = userStore.getUserInfo
  let userFieldFixed = ''
  let userFieldUnFixed = ''
  fixLeftList.value.forEach((v) => {
    userFieldFixed += `${v.id},`
  })
  onList.value.forEach((v) => {
    userFieldUnFixed += `${v.id},`
  })
  userFieldFixed = userFieldFixed.slice(0, userFieldFixed.length - 1)
  userFieldUnFixed = userFieldUnFixed.slice(0, userFieldUnFixed.length - 1)
  savefield(props.reviewType, userInfo.id, userFieldFixed, userFieldUnFixed)
  const columns: any[] = [
    {
      type: 'selection',
      fixed: 'left',
      width: 50,
    },
  ]

  const leftList = fixLeftList.value.map((item) => {
    return {
      title: item.name,
      key: item.id,
      fixed: 'left',
      width: 120,
    }
  })

  const unfixList = onList.value.map((item) => {
    return {
      title: item.name,
      key: item.id,
      width: 120,
    }
  })

  columns.push(...leftList, ...unfixList)
  emit('commit', columns)
}

defineExpose({
  showModal,
})

// generatList()

const selectIds = ref<string[]>([])

function onCheckAllChange(value) {
  const ids: string[] = []
  for (const item of offList.value) {
    if (!item.fix) {
      item.checked = value
      ids.push(item.id)
    }
  }
  if (value) {
    offList.value.forEach((v) => {
      if (!v.checked)
        onList.value.push(v)
    })
  }
  else {
    onList.value = []
    fixLeftList.value = []
    offList.value.forEach((v) => {
      if (v.fix)
        fixLeftList.value.push(v)
    })
  }
  selectIds.value = value ? ids : []
}

function onCheckChange(checked: any, item: any) {
  item.checked = checked
  if (checked) {
    onList.value.push(item)
  }
  else {
    let index = onList.value.findIndex(v => v.id == item.id)
    if (index > -1) {
      onList.value.splice(index, 1)
    }
    else {
      index = fixLeftList.value.findIndex(v => v.id == item.id)
      fixLeftList.value.splice(index, 1)
    }
  }
  // TODO 与现有逻辑冲突 暂时注释
  // if (index === -1 && checked) selectIds.value.push(item.id);
  // else selectIds.value.splice(index, 1);
}

const showIds = computed(() => {
  return onList.value.map((item) => {
    return item.id
  })
})

watch(
  () => selectIds.value.length,
  (newVal, oldVal) => {
    if (newVal === oldVal)
      return

    const action = newVal > oldVal ? 'add' : 'remove'
    const diff: string[]
      = action === 'add'
        ? difference(selectIds.value, showIds.value)
        : difference(showIds.value, selectIds.value)

    if (diff.length === 0)
      return

    if (action === 'add') {
      for (const item of offList.value) {
        if (!item.fix && diff.includes(item.id)) {
          onList.value.push({
            id: item.id,
            name: item.name,
            fix: item.fix || false,
            width: 120,
          })
        }
      }
    }
    else {
      const list = onList.value
      for (let index = 0; index < list.length; index++) {
        const item = list[index]
        if (!item.fix && diff.includes(item.id)) {
          list.splice(index, 1)
          return
        }
      }
    }
  },
)

watch(
  () => showIds.value.length,
  (newVal, oldVal) => {
    if (newVal === oldVal)
      return

    const diff = difference(selectIds.value, showIds.value)

    if (diff.length === 0)
      return

    for (const item of offList.value) {
      if (!item.fix && diff.includes(item.id)) {
        const index = selectIds.value.indexOf(item.id)
        item.checked = false
        selectIds.value.splice(index, 1)
      }
    }
  },
)

function clearDragSource() {
  onList.value = onList.value.filter((item) => {
    return item.fix === true
  })
}

function removeHandler(id: string, type: 'fix' | 'unfix') {
  const list = type === 'fix' ? fixLeftList.value : onList.value

  let index = list.findIndex((item) => {
    return item.id === id
  })

  if (index !== -1)
    list.splice(index, 1)
  index = offList.value.findIndex(v => v.id == id)
  if (index !== -1) {
    offList.value[index].checked = false
  }
  else {
    index = fixLeftList.value.findIndex(v => v.id == id)
    fixLeftList.value[index].checked = false
  }
}

const indeterminate = computed(() => {
  return (
    onList.value.length
    + fixLeftList.value.length
    - offList.value.filter(v => v.fix).length
    > 0
    && offList.value.length - offList.value.filter(v => v.fix).length
    > onList.value.length
    + fixLeftList.value.length
    - offList.value.filter(v => v.fix).length
  )
})
</script>

<template>
  <n-modal v-model:show="show" transform-origin="center">
    <n-card
      class="cardstyle"
      :bordered="false"
      size="huge"
      role="dialog"
      aria-modal="true"
    >
      <div class="wrapper">
        <span class="wrapper-title">自定义显示列</span>
        <div class="wrapper-bar">
          <div class="wrapper-info">
            <span :style="{ 'margin-left': '18px' }">字段信息</span>
          </div>
        </div>
        <n-grid cols="4" class="mt-4 proCard" responsive="screen" :x-gap="24">
          <n-grid-item span="3">
            <NCard
              :title="allCount"
              class="dragcardStyle"
              :segmented="{ content: true, footer: true }"
              size="small"
              :bordered="false"
            >
              <div>
                <n-input placeholder="搜索关键字">
                  <template #suffix>
                    <SvgIcon size="14px" name="magnifying-1" color="#999999" />
                  </template>
                </n-input>
                <div class="draggable-ul left-wrap">
                  <div class="draggable-li" :class="{ checkAll: indeterminate }">
                    <n-checkbox
                      v-model:checked="checkAll"
                      label="全部"
                      :indeterminate="indeterminate"
                      @update:checked="onCheckAllChange"
                    />
                  </div>
                  <div class="content">
                    <div
                      v-for="item in offList"
                      :key="item.id"
                      style="width: 170px"
                      :class="{ 'disable-check': item.fix }"
                      class="draggable-li"
                    >
                      <n-checkbox
                        v-model:checked="item.checked"
                        :label="item.name"
                        :disabled="item.fix"
                        @update:checked="onCheckChange($event, item)"
                      />
                    </div>
                  </div>
                </div>
              </div>
            </NCard>
          </n-grid-item>
          <n-grid-item>
            <NCard
              :title="selectCount"
              class="dragcardStyle"
              :segmented="{ content: true, footer: true }"
              size="small"
              :bordered="false"
            >
              <template #header-extra>
                <span class="textbtnStyle" @click="clearDragSource">恢复默认</span>
              </template>
              <div>
                <n-input placeholder="搜索关键字">
                  <template #suffix>
                    <SvgIcon size="14px" name="magnifying-1" />
                  </template>
                </n-input>
                <div class="drag-wrapper">
                  <div>固定在左侧</div>
                  <VueDraggable
                    v-model="fixLeftList"
                    class="draggable-ul"
                    :animation="150"
                    group="show"
                  >
                    <div
                      v-for="item in fixLeftList"
                      :key="item.id"
                      :class="{ fix: item.fix }"
                      class="cursor-move draggable-item"
                    >
                      <SvgIcon name="drag" size="14" color="#666666" />
                      <span class="ml-2">{{ item.name }}</span>
                      <!-- <SvgIcon
                        v-if="!item.fix"
                        size="16px"
                        style="display: block; margin-left: auto; cursor: pointer"
                        name="clear"
                        @click="removeHandler(item.id, 'fix')"
                      /> -->
                    </div>
                  </VueDraggable>
                  <div>不固定</div>
                  <VueDraggable
                    v-model="onList"
                    class="draggable-ul"
                    :animation="150"
                    group="show"
                  >
                    <div
                      v-for="item in onList"
                      :key="item.id"
                      :class="{ fix: item.fix }"
                      class="cursor-move draggable-item"
                    >
                      <SvgIcon name="drag" size="14" color="#666666" />
                      <span class="ml-2">{{ item.name }}</span>
                      <SvgIcon
                        v-if="!item.fix"
                        size="16px"
                        style="display: block; margin-left: auto; cursor: pointer"
                        name="clear"
                        @click="removeHandler(item.id, 'unfix')"
                      />
                    </div>
                  </VueDraggable>
                </div>
              </div>
            </NCard>
          </n-grid-item>
        </n-grid>
      </div>

      <template #footer>
        <div class="wrapper-footer">
          <n-button type="info" @click="handleSumbit">
            确定
          </n-button>
          <n-button secondary style="margin-left: 15px" @click="closeModal">
            取消
          </n-button>
        </div>
      </template>
    </n-card>
  </n-modal>
</template>

<style lang="less" scoped>
.wrapper {
  display: flex;
  flex-direction: column;
  border-bottom: 1px solid #e8e8e8;
  padding-bottom: 32px;

  &-title {
    font-weight: bold;
    font-size: 16px;
  }

  &-bar {
    width: 100%;
    margin-top: 20px;
  }

  &-footer {
    display: flex;
    justify-content: flex-end;
  }

  &-info {
    font-weight: bold;
    position: relative;
    color: #333333;
    font-size: 14px;
    background: #f8f8f8;

    &:before {
      background-color: #1980ff;
      content: "";
      width: 5px;
      border-radius: 2px;
      top: 0;
      bottom: 0;
      position: absolute;
    }
  }
}

.dragcardStyle {
  --n-padding-bottom: 0px !important;
  --n-padding-left: 0px !important;
}

.cardstyle {
  width: 820px;
  // --n-padding-bottom: 20px;
  --n-padding-left: 24px;
  --n-padding-right: 24px;
  --n-padding-top: 20px;
  // padding: 20px 24px  0 24px !important
}

.textbtnStyle {
  cursor: pointer;
  color: #507afd;
}

.drag-wrapper {
  border: 1px solid #cad2dd;
  color: gray;
  padding: 12px;
}

.draggable-ul {
  width: 100%;
  overflow: hidden;
  border-top: 0px;
  border-radius: 2px;
  display: block;

  .content {
    display: flex;
    flex-wrap: wrap;
  }

  .draggable-li {
    padding: 10px 16px;
    color: #333;
  }

  .draggable-item {
    padding: 11px 16px;
    color: #333;
    display: flex;
    align-items: center;
    // border-bottom: 1px solid #e8e8e8;
  }

  .disable-check {
    color: gainsboro;
  }
}

::v-deep(.n-card.n-card--content-segmented > .n-card__content:not(:first-child)) {
  border: 0px;
}

::v-deep(.n-card > .n-card-header) {
  --n-padding-top: 0px;
  --n-padding-bottom: 12px;
}
.left-wrap {
  border: 1px solid #cbd3de;
}
::v-deep(.n-card > .n-card-header .n-card-header__main) {
  font-weight: lighter !important;
  font-size: 14px;
  color: #666666;
}
::v-deep(.n-scrollbar) {
  border-top: none !important;
}
::v-deep(.n-button--info-type) {
  background: #507afd !important;
}
::v-deep(.n-button--default-type) {
  border: 1px solid #cad2dd !important;
}
// ::v-deep(.n-card__content){
//   padding: 20px 24px  0 24px !important;
// }
::v-deep(.checkAll .n-checkbox.n-checkbox--indeterminate .n-checkbox-box) {
  background: none;
  border: none;
}
::v-deep(.checkAll .n-checkbox-box__border) {
  border: 1px solid #e8e8e8 !important;
}
::v-deep(.checkAll .n-checkbox-icon) {
  border: 3px solid #fff;
  background: #1980ff;
}
::v-deep(.checkAll .n-checkbox-icon svg) {
  display: none !important;
}
</style>
