<script lang="ts" setup>
import { cloneDeep, difference } from 'lodash-es'
import { computed, defineEmits, defineProps, 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: () => 1,
    require: true,
  },
})

const emit = defineEmits(['onOk'])

// 左侧隐藏列表
const offList = ref<any[]>([])
// 右侧显示列表
const onList = ref<any[]>([])
// 固定默认列表
const fixList = ref<any[]>([])

const offShowList = ref<any[]>([])
const onShowList = ref<any[]>([])
const fixShowList = ref<any[]>([])

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

const selectCount = computed(() => {
  let baseNum = 0
  offList.value.forEach((item) => {
    if (item.fix)
      baseNum++
  })
  return `显示字段(共${baseNum + onList.value.length}个)`
  // return `显示字段(共${onList.value.length}个)`
})

const show = ref(false)
const checkAll = computed(() => {
  let baseNum = 0
  offList.value.map((v) => {
    if (v.fix)
      baseNum += 1
    return v
  })
  return onList.value.length == offList.value.length - baseNum
})

function showModal() {
  show.value = true
}

function closeModal() {
  show.value = false
}

async function handleSumbit(e: MouseEvent) {
  const userStore = useUser()
  const userInfo = userStore.getUserInfo
  let userFieldFixed = ''
  fixList.value.map((v) => {
    userFieldFixed += `${v.id},`
    return v
  })
  onList.value.map((v) => {
    userFieldFixed += `${v.id},`
    return v
  })
  userFieldFixed = userFieldFixed.slice(0, userFieldFixed.length - 1)
  savefield(props.reviewType, userInfo.id, userFieldFixed)
  e.preventDefault()
  closeModal()
  emit('onOk')
}

defineExpose({
  showModal,
})

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)
    }
  }
  for (const item of offShowList.value) {
    if (!item.fix)
      item.checked = value
  }

  selectIds.value = value ? ids : []
  if (value) {
    offList.value.map((v) => {
      if (!v.checked)
        onList.value.push(v)
      return v
    })
    onShowList.value = cloneDeep(onList.value)
  }
  else {
    onList.value = []
    onShowList.value = []
  }
}

function onCheckChange(checked: any, item: any) {
  const index = selectIds.value.indexOf(item.id)
  // TODO 禁止选中六个以上字段代码 提示逻辑
  // if (index == -1 && selectIds.value.length >= 6) {
  //   item.checked = false;
  //   message.error("自定义任务卡片字段一共勾选数量不能超过6个");
  //   return;
  // }
  item.checked = checked
  const currentIndex = offList.value.findIndex(v => v.id == item.id)
  offList.value[currentIndex].checked = checked
  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
      = 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,
          })
        }
      }
      onShowList.value = cloneDeep(onList.value)
    }
    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)
          onShowList.value.splice(index, 1)
          index--
        }
      }
      console.log(onShowList.value, list, 'onShowList')
    }
  },
)

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
  })
  onShowList.value = cloneDeep(onList.value)
  offList.value = offList.value.map(item => ({
    ...item,
    checked: item.fix,
  }))
  offShowList.value = cloneDeep(offList.value)
}

function removeHandler(id: string) {
  let index = onList.value.findIndex((item) => {
    return item.id === id
  })
  if (index !== -1) {
    onList.value.splice(index, 1)
    onShowList.value.splice(index, 1)
  }

  index = offList.value.findIndex(v => v.id == id)
  offList.value[index].checked = false
  offShowList.value = cloneDeep(offList.value)
}
function initData() {
  offList.value = []
  onList.value = []
  fixList.value = []
  offShowList.value = []
  onShowList.value = []
  fixShowList.value = []
  selectIds.value = []
}
async function getData(type = '') {
  initData()
  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(',')
  if (!type || type == 'off') {
    offList.value = []
    allList?.map((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)
        fixList.value.push(item)
      else offList.value.push(item)
      return v
    })
    offList.value.unshift(...fixList.value)
  }
  if (!type || type == 'on') {
    useList?.userFieldFixed?.split(',').map((v) => {
      let item = allList.find(v2 => v2.name == v)
      if (item) {
        item = {
          name: item.fieldDesc,
          id: item.name,
          fix: item.isrequired == 2,
          checked: true,
        }
        selectIds.value.push(item.id)
        if (!item.fix)
          onList.value.push(item)
      }
      return v
    })
  }
  offShowList.value = cloneDeep(offList.value)
  fixShowList.value = cloneDeep(fixList.value)
  onShowList.value = cloneDeep(onList.value)
}

onMounted(() => getData())

const indeterminate = computed(() => {
  let baseNum = 0
  offList.value.map((v) => {
    if (v.fix)
      baseNum += 1
    return v
  })
  return (
    onShowList.value.length > 0
    && offShowList.value.length - baseNum > onShowList.value.length
  )
})
function queryData(value, type) {
  if (value) {
    if (type == 'off') {
      offShowList.value = offList.value.filter(item => item.name.includes(value))
    }
    else {
      onShowList.value = onList.value.filter(item => item.name.includes(value))
      fixShowList.value = fixList.value.filter(item => item.name.includes(value))
    }
  }
  else {
    // getData(type);
    if (type == 'off') {
      offShowList.value = cloneDeep(offList.value)
    }
    else {
      onShowList.value = cloneDeep(onList.value)
      fixShowList.value = cloneDeep(fixList.value)
    }
  }
}

const moreThanSix = computed(() => {
  return selectIds.value.length >= 6
})
</script>

<template>
  <n-modal v-model:show="show" transform-origin="center" :mask-closable="false">
    <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="搜索关键词"
                  @input="(value) => queryData(value, 'off')"
                >
                  <template #suffix>
                    <SvgIcon size="14px" name="magnifying-1" />
                  </template>
                </n-input>
                <div class="draggable-ul">
                  <!-- <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 offShowList"
                      :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 || (!item.checked && moreThanSix)"
                        @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="搜索关键词"
                  @input="(value) => queryData(value, 'on')"
                >
                  <template #suffix>
                    <SvgIcon size="14px" name="magnifying-1" />
                  </template>
                </n-input>
                <div class="draggable-title">
                  系统默认
                </div>
                <div class="draggable-ul" style="border-bottom: none">
                  <div
                    v-for="item in fixShowList"
                    :key="item.id"
                    :class="{ fix: item.fix }"
                    class="cursor-move draggable-item"
                  >
                    <span class="ml-2">{{ item.name }}</span>
                  </div>
                </div>
                <div class="draggable-title" style="border-top: none">
                  自定义配置
                </div>
                <VueDraggable
                  v-model="onList"
                  class="draggable-ul"
                  :animation="150"
                  group="shared"
                >
                  <div
                    v-for="item in onShowList"
                    :key="item.id"
                    :class="{ fix: item.fix }"
                    class="cursor-move draggable-item"
                  >
                    <SvgIcon name="drag" size="14" />
                    <span class="ml-2">{{ item.name }}</span>
                    <SvgIcon
                      v-if="!item.fix"
                      size="16"
                      style="display: block; margin-left: auto; cursor: pointer"
                      name="clear"
                      @click="removeHandler(item.id)"
                    />
                  </div>
                </VueDraggable>
              </div>
            </NCard>
          </n-grid-item>
        </n-grid>
      </div>
      <template #footer>
        <div class="wrapper-footer">
          <n-button
            type="info"
            @click="
              ($event) => {
                handleSumbit($event);
                getData();
              }
            "
          >
            确定
          </n-button>
          <n-button
            secondary
            style="margin-left: 15px"
            @click="
              getData();
              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 {
    background-color: #e8e8e8;
    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;
}

.textbtnStyle {
  cursor: pointer;
  color: #1980ff;
}
.draggable-title {
  border: 1px solid #cad2dd;
  border-bottom: none;
  color: gray;
  padding: 12px;
}
.draggable-ul {
  width: 100%;
  overflow: hidden;
  border: 1px solid #cad2dd;
  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;
}
::v-deep(.n-card > .n-card-header .n-card-header__main) {
  font-weight: bolder !important;
}
::v-deep(.n-scrollbar) {
  border-top: none !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;
}
::v-deep(.n-card > .n-card-header .n-card-header__main) {
  font-weight: lighter !important;
  font-size: 14px;
  color: #666666;
}
::v-deep(.n-button--info-type) {
  background: #507afd !important;
}
::v-deep(.n-button--default-type) {
  border: 1px solid #cad2dd !important;
  background-color: #fff;
}
</style>
