<script lang="ts" setup>
import { computed, defineOptions, ref, watch } from 'vue'
import { VueDraggable } from 'vue-draggable-plus'
import { difference } from 'lodash-es'
import { setFilter } from '@/api/home/filter'
import { asideMap } from '@/config/aside'
import { useConfig } from '@/store/modules/asideConfig'

defineOptions({ name: 'CustomFilterModal' })

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

function showModal() {
  show.value = true
}

function closeModal() {
  show.value = false
}

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

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

const selectCount = computed(() => {
  return `全部筛选(共${onList.value.length}个)`
})

defineExpose({
  showModal,
})

function generateDefaultList(config) {
  return Object.keys(asideMap).reduce((acc, key) => {
    const { label, isDefaultFilter } = asideMap[key]

    // 个人配置开启且系统配置开启
    if (isDefaultFilter && config[key] === 'Y') {
      const config = {
        id: key,
        name: label || '未配置',
        fix: true,
        checked: true,
      }
      return [...acc, config]
    }
    else {
      return acc
    }
  }, [])
}

function generatList(config, customConfig) {
  const keys = Object.keys(config)
  let onList: object[] = []
  const offList: object[] = []
  const showKeys = customConfig.searchcount.split(',').map((key: string) => key.toLowerCase())

  for (const key of keys) {
    if (!key.startsWith('iz') || config[key] === 'N' || asideMap[key] === undefined)
      continue

    const name = asideMap[key]?.label
    const isDefaultFilter = asideMap[key]?.isDefaultFilter

    // 系统配置为Y，且不是默认配置
    if (!isDefaultFilter) {
      offList.push({
        id: key,
        name: name || '未配置',
        fix: isDefaultFilter,
        checked: asideMap[key].isDefaultFilter,
      })
    }
  }

  onList = showKeys.reduce((acc, key) => {
    // 也需要系统配置开启（可能个人开启后，系统配置关闭）
    if (config[key] === 'Y') {
      const config = {
        id: key,
        name: asideMap[key].label || '未配置',
        fix: asideMap[key].isDefaultFilter,
      }
      return [...acc, config]
    }
    else {
      return acc
    }
  }, [])

  const fixedList = generateDefaultList(config)

  offList.unshift(...fixedList)
  return { showList: onList, hideList: offList }
}

configStore.$subscribe(() => {
  const config = configStore.getConfig
  const customConfig = configStore.getCustomConfig

  if (config === null || customConfig === null)
    return

  const { showList, hideList } = generatList(config, customConfig)
  onList.value = showList
  offList.value = hideList
})

async function handleSumbit(e: MouseEvent) {
  e.preventDefault()

  const param = onList.value.map((item) => {
    return item.id
  }).join(',')

  await setFilter({ searchcount: param })
  configStore.fetchCustomConfig()
  closeModal()
}

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)
    }
  }

  selectIds.value = value ? ids : []
}

function onCheckChange(checked: any, item: any) {
  const index = selectIds.value.indexOf(item.id)

  item.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,
          })
        }
      }
    }
    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)
          index--
        }
      }
    }
  },
)

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) {
  const index = onList.value.findIndex((item) => {
    return item.id === id
  })

  if (index !== -1)
    onList.value.splice(index, 1)
}
</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="2" class="mt-4 proCard" responsive="screen" :x-gap="24">
          <n-grid-item>
            <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" />
                  </template>
                </n-input>
                <n-scrollbar style="max-height: 500px;border: 1px solid #cad2dd;border-radius: 2px;">
                  <div class="draggable-ul">
                    <div class="draggable-li">
                      <n-checkbox v-model:checked="checkAll" label="全部" @update:checked="onCheckAllChange" />
                    </div>
                    <div
                      v-for="item in offList" :key="item.id" :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>
                </n-scrollbar>
              </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>
                <n-scrollbar style="max-height: 500px;border: 1px solid #cad2dd;border-radius: 2px;" class="scroll">
                  <VueDraggable v-model="onList" class="draggable-ul" :animation="150" group="shared">
                    <div
                      v-for="item in onList" :key="item.id" :class="{ fix: item.fix }"
                      class="cursor-move draggable-li"
                    >
                      <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)"
                      />
                    </div>
                  </VueDraggable>
                </n-scrollbar>
              </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;

  &-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;

    &: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: 620px;
  --n-padding-bottom: 20px;
  --n-padding-left: 24px;
}

.textbtnStyle {
  cursor: pointer;
  color: #1980FF;
}

.draggable-ul {
  width: 100%;
  overflow: hidden;

  .draggable-li {
    width: 100%;
    padding: 10px 16px;
    color: #333;
    border-bottom: 1px solid #efeff5;
    display: flex;
    align-items: center;
  }

  .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
}
</style>
