<template>
  <JCollapse :data="[{ title: 'IP集合', id: '1' }]" @update="(item: any) => listEditOpen = true"
    @delete="(item: any) => ipDeletable = !ipDeletable"
    :deleteText="ipDeletable ? t('common.cancelButtonText') : t('marketingApps.delete')" :updateText="t('marketingApps.add')" :activeNames="['1']">
    <template #default>
      <div class="border-b p-2 items-center flex flex-wrap collapse-group min-h-[40px]" v-for="type in [IpType.WHITE, IpType.BLACK]"
        :key="type">
        <div class="collapse-group-name">{{ type === IpType.WHITE ? t('marketingApps.whiteList') : t('marketingApps.blackList') }}：</div>
        <div class="tag-content" v-if="getTargetList(type).length > 0">
          <template v-for="item in getTargetList(type)" :key="item.id">
            <!-- 单个 -->
            <el-tag v-if="item.sourceType == 2" effect="light" :closable="ipDeletable" @close="handleDeleteIp(item)"
              color="#f4f4f4" round class="mr-1 mb-1 cursor-pointer">
              <span class="ellipsis">{{ ipSplicing(item.startIp, item.endIp) }}</span>
            </el-tag>
            <!-- 分组 -->
            <el-popover v-else width="200" trigger="hover" placement="top" @show="onLoadDetail(item)">
              <div v-if="item.list.length > 0" class="flex flex-wrap break-all">
                <span v-for="ip in item.list" :key="String(ip)" class="mr-2">{{ typeof ip == 'string' ? ip : ipSplicing(ip.startIp, ip.endIp) }}</span>
              </div>
              <div v-else>{{ t('marketingApps.noData') }}</div>
              <template #reference>
                <el-tag effect="light" :closable="ipDeletable" @close="handleDeleteIp(item)" color="#f4f4f4" round
                  class="mr-1 mb-1 cursor-pointer">
                  <span class="ellipsis" v-if="item.groupName">{{ item.groupName.length > 30 ?
                    item.groupName.substring(0, 30) + '...' : item.groupName }}</span>
                </el-tag>
              </template>
            </el-popover>
          </template>
        </div>
        <div class="text-gray-400" v-else>--</div>
      </div>
    </template>
  </JCollapse>
  <IpEdit v-model:open="listEditOpen" @onsuccess="addIp" />
</template>
<script setup lang="ts" name="ipCollapse">
const JCollapse = defineAsyncComponent(() => import('/@/components/JCollapse/index.vue'));
const IpEdit = defineAsyncComponent(() => import('./ipEdit.vue'));
import { useI18n } from 'vue-i18n';
import { getGroupDetail } from '/@/api/marketing/config';
import { ipSplicing } from '/@/utils/ipUpdate';
import { useMessage } from '/@/hooks/message';
import { SourceType, IpType, IpMode, IpItem } from '../types';

const props = defineProps(['data']);
const emit = defineEmits(['refresh', 'ips', 'delIps']);
const { t } = useI18n();

const ips = ref<IpItem[]>([]);
const ipDeletable = ref(false);
const listEditOpen = ref(false);
const delIps = ref<string[]>([]);

watch(ips, (newVal) => emit('ips', newVal), { deep: true, immediate: true });
watch(delIps, (newVal) => emit('delIps', newVal), { deep: true, immediate: true });

const getTargetList = (ipType: number) => ips.value.filter(i => i.ipType === ipType);

const setTargetList = (ipType: number, newList: IpItem[]) => {
  ips.value = [
    ...ips.value.filter(i => i.ipType !== ipType),
    ...newList
  ];
};

watchEffect(() => {
  if (props.data) {
    ips.value = props.data.map((item: any) => ({ ...item, list: [] }));
  }
});

const handleDeleteIp = (deleteItem: IpItem) => {
  if (!deleteItem.modify && !delIps.value.includes(deleteItem.id as string)) {
    delIps.value.push(deleteItem.id as string);
  }
  ips.value = ips.value.filter(i => {
    if (i.id !== deleteItem.id) return true;
    if (deleteItem.sourceType === SourceType.GROUP) return i.groupId !== deleteItem.groupId;
    return i.startIp !== deleteItem.startIp || i.endIp !== deleteItem.endIp;
  });
};

const onLoadDetail = async (item: any) => {
  if (item.list.length || item.modify) return;
  const val = await getGroupDetail({ id: item.groupId });
  item.list = val.data.ips.map((item: any) => ipSplicing(item.startIp, item.endIp));
};

function addGroupsUnique(newGroups: IpItem[], ipType: number) {
  const targetList = getTargetList(ipType);
  const conflictType = ipType === IpType.WHITE ? IpType.BLACK : IpType.WHITE;
  const conflictList = getTargetList(conflictType);
  const existIds = new Set(targetList.filter(i => i.sourceType === SourceType.GROUP).map(i => i.groupId));
  const conflictIds = new Set(conflictList.filter(i => i.sourceType === SourceType.GROUP).map(i => i.groupId));
  const conflict = newGroups.find(i => conflictIds.has(i.id as string));
  if (conflict) {
    useMessage().error(`分组 ${conflict.groupName} 已存在于 ${ipType === IpType.WHITE ? '黑名单' : '白名单'} 中`);
    return;
  }

  const filtered = newGroups.filter(i => !existIds.has(i.id as string));

  if (filtered.length) {
    const processedGroups = filtered.map(item => ({
      ipType,
      sourceType: SourceType.GROUP,
      groupId: item.id as string,
      groupName: item.groupName,
      ipMode: IpMode.IP,
      startIp: '',
      endIp: '',
      modify: true,
      list: item.list || [],
    }));
    setTargetList(ipType, [...targetList, ...processedGroups]);
  } else {
    useMessage().error(t('marketingApps.addIpTip'));
  }
}

function addSinglesUnique(newSingles: IpItem[], ipType: number) {
  const targetList = getTargetList(ipType);
  const conflictType = ipType === IpType.WHITE ? IpType.BLACK : IpType.WHITE;
  const conflictList = getTargetList(conflictType);

  const existIps = new Set(targetList.filter(i => i.sourceType === SourceType.DOMAIN).map(i => i.startIp));
  const conflictIps = new Set(conflictList.filter(i => i.sourceType === SourceType.DOMAIN).map(i => i.startIp));

  const conflict = newSingles.find(i => conflictIps.has(i.startIp));
  if (conflict) {
    console.log(conflict);
    useMessage().error(`IP ${conflict.startIp} 已存在于 ${ipType === IpType.WHITE ? '黑名单' : '白名单'} 中`);
    return;
  }

  const filtered = newSingles.filter(i => !existIps.has(i.startIp));

  if (filtered.length) {
    const processedSingles = filtered.map(i => ({
      endIp: i.endIp,
      groupId: '',
      groupName: '',
      ipMode: i.endIp ? IpMode.IPRange : IpMode.IP,
      startIp: i.startIp,
      sourceType: SourceType.DOMAIN,
      modify: true,
      ipType,
      list: []
    }));
    setTargetList(ipType, [...targetList, ...processedSingles]);
  } else {
    useMessage().error(t('marketingApps.addIpTip2'));
  }
}

const addIp = (data: IpItem[], sourceType: SourceType.GROUP | SourceType.DOMAIN, ipType: IpType.WHITE | IpType.BLACK) => {
  const ipTypeNum = Number(ipType);
  if (sourceType === SourceType.DOMAIN) {
    data.length && addSinglesUnique(data, ipTypeNum);
  } else {
    data.length && addGroupsUnique(data, ipTypeNum);
  }
};
</script>
<style lang="scss">
@import '/@/theme/mixins/index.scss';

.el-collapse-item__content {
  padding: 0;
}

.ellipsis {
  @include text-ellipsis(1);
}
</style>