<template>
  <el-dialog title="网络配置" :visible.sync="dialog.visible" width="800px" append-to-body>
    <basic-form :model="configs" ref="addData">
      <div :span="24" v-for="(cell, index) in configs.networkCardConfigs" :key="index" class="m-b">
        <basic-form-item label="IP池：" validate="required" :prop="`networkCardConfigs.${index}.ipPoolId`">
          <el-select class="w" v-model="cell.ipPoolId" @change="getIp(cell)" placeholder="请选择 IP 池">
            <el-option :label="item.ipPoolName" :value="item.ipPoolId" v-for="(item, index) in ippools" :key="index"></el-option>
          </el-select>
          <el-radio-group class="m-l-md" v-model="cell.ipPolicy" size="small" @change="getIp(cell)">
            <el-radio-button label="Auto">自动</el-radio-button>
            <el-radio-button label="Manual">手动</el-radio-button>
          </el-radio-group>
          <template v-if="cell.ipPolicy && cell.ipPolicy === 'Manual'">
            <el-select v-loading="cell.loading" placeholder="请输入IP进行搜索" filterable class="m-l-md w" v-model="cell.address" size="small" multiple @visible-change="(flag) => conditionIp(flag, cell)" :filter-method="(query) => ipFilter(query, cell)" @change="selectIpChange(cell)">
              <el-option v-for="item in cell.showIps" :key="item" :label="item" :value="item" :disabled="calcAddress(cell, item)"></el-option>
            </el-select>
          </template>
          <el-button type="text" class="m-l-md" @click="addCard">新增</el-button>
          <el-button type="text" class="m-l-md" v-if="configs.networkCardConfigs.length > 1" @click="configs.networkCardConfigs.splice(index, 1)">删除</el-button>
        </basic-form-item>
        <div v-if="subLocation.vendorType === 'CECSTACK'" class="m-t">
          <basic-form-item label="所属网络：" validate="required" :prop="`networkCardConfigs.${index}.subnetUuid`">
            <el-select class="w m-r" v-model="cell.vpcUuid" @change="changeVPC(cell)" placeholder="请选择VPC">
              <el-option v-for="item in cell.vpcList" :label="`${item.name}(${item.vpcId})`" :value="item.vpcId" :key="item.vpcId"></el-option>
            </el-select>
            <el-select class="w" v-model="cell.subnetUuid" placeholder="请选择子网">
              <el-option v-for="item in cell.subnetList" :label="`${item.name}(${item.value})`" :value="item.value" :key="item.value"></el-option>
            </el-select>
          </basic-form-item>
          <basic-form-item label="安全组：" validate="required" :prop="`networkCardConfigs.${index}.groups`">
            <el-select class="w" v-model="cell.groups" multiple placeholder="请选择安全组">
              <el-option v-for="item in cell.groupList" :label="`${item.name}(${item.groupUuid})`" :value="item.groupUuid" :key="item.groupUuid"></el-option>
            </el-select>
          </basic-form-item>
        </div>
      </div>
    </basic-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click.native="dialog.visible = false">取消</el-button>
      <el-button type="primary" @click.native="handleSubmit">确定</el-button>
    </div>
  </el-dialog>
</template>
<script>
import { conditionIp, getSubnet, getVpc, getGroup } from 'services/platform/index'
import { cloneDeep, uniq } from 'lodash-es'
export const CECSTACK_DEFAULT_CONFIG = {
  vpcList: [],
  subnetList: [],
  groupList: [],
  vpcUuid: '',
  networkType: 'Geneve',
  subnetUuid: '',
  ipAddress: '',
  groups: []
}
export const CLOUDTOWER_DEFAULT_CONFIG = {
  operation: 'newNet',
  mac: '',
  model: 'VIRTIO',
  netmask: '',
  link: 'up'
}
export default {
  props: {
    dialog: {
      type: Object,
      default: () => {}
    },
    itemData: {
      type: [Object, Boolean]
    },
    disabled: {
      type: Boolean
    }
  },
  data() {
    return {
      ippools: [],
      prefixNodeIps: {}
    }
  },
  computed: {
    subLocation() {
      return this.dialog.row.subLocation
    },
    configs() {
      return this.dialog.row.configs
    },
    count() {
      const {
        nodes = 1,
        emption: { count }
      } = this.dialog.row
      return nodes * count
    },
    selectedIps() {
      const ips = []
      this.configs.networkCardConfigs.map(({ ipPolicy, address }) => {
        if (ipPolicy == 'Manual') {
          ips.push(...address)
        }
      })
      return ips
    }
  },
  created() {
    this.getIpPool()
    this.configs.networkCardConfigs.map((item) => {
      if (item.address.length) {
        if (this.prefixNodeIps[item.ipPoolId]) {
          this.prefixNodeIps[item.ipPoolId].push(...item.address)
        } else {
          this.prefixNodeIps[item.ipPoolId] = [...item.address]
        }
      }
      this.getIp(item, !!this.itemData)
      this.getVpcList(item, !!this.itemData)
      this.getSgroupList(item, !!this.itemData)
    })
  },
  watch: {
    count() {
      this.configs.networkCardConfigs.map((item) => {
        this.getIp(item)
      })
    }
  },
  methods: {
    addCard() {
      if (this.configs.networkCardConfigs.length === 3) return this.$message.warning('最多添加3张网卡')
      const first = this.configs.networkCardConfigs[0]
      let config = {}
      switch (this.subLocation.vendorType) {
        case 'CECSTACK':
          config = { ...CECSTACK_DEFAULT_CONFIG, vpcList: first.vpcList, subnetList: first.subnetList, groupList: first.groupList }
          break
        case 'CLOUDTOWER':
          config = CLOUDTOWER_DEFAULT_CONFIG
          break
        default:
          break
      }
      this.configs.networkCardConfigs.push({
        networkCardId: first.networkCardId,
        ipPolicy: 'Auto',
        ipPoolId: '',
        ipPoolName: '',
        address: [],
        portGroupId: '',
        loading: false,
        ...config
      })
    },
    conditionIp(flag, cell = {}) {
      // 下拉框出现
      if (flag) return
      const { address = [], ipPoolId } = cell
      if (!address.length) return
      // 上一个审批节点时传输的,就已经是锁定状态了
      // 以 addresses 为基础, 过滤不在 prefixNodeIps 中的 ip
      const filterAddress = address.filter((ip) => !this.prefixNodeIps[cell.ipPoolId]?.includes(ip))
      if (!filterAddress.length) return
      conditionIp({
        condition: JSON.stringify({
          condition: 'checkIp',
          poolId: ipPoolId,
          ips: filterAddress
        })
      }).then((data) => {
        if (!data.success) {
          this.$message.success(data.message)
          cell.address = []
        }
      })
    },
    selectIpChange(cell) {
      if (!cell.address.length) cell.showIps = this.ippools.find(({ ipPoolId }) => ipPoolId === cell.ipPoolId).freezeAllIps.slice(0, 20)
    },
    calcAddress(cell, ip) {
      // 其他虚机中是否已经选择过 禁用
      let flag = false
      if (this.selectedIps.includes(ip)) flag = true
      // 超出数量禁用
      if (cell.address.length >= this.count) flag = true
      return flag
    },
    ipFilter(query = '', cell) {
      const freezeAllIps = this.ippools.find(({ ipPoolId }) => ipPoolId === cell.ipPoolId)?.freezeAllIps || []
      if (!query) return freezeAllIps.slice(0, 20)
      // 上个节点已选
      const preIps = this.prefixNodeIps[cell.ipPoolId]?.filter((ip) => ip.includes(query)) || []
      // 已过滤
      const arr = freezeAllIps.filter((ip) => ip.includes(query)).slice(0, 20)
      // 合并并去重
      this.$set(cell, 'showIps', uniq([...preIps, ...cell.address, ...arr]))
      return cell.showIps
    },
    getVpcList(cell, isInit = false) {
      if (this.disabled || this.subLocation.vendorType !== 'CECSTACK' || !this.subLocation.vendorId || !this.subLocation.region) return
      getVpc({
        simple: true,
        params: this.$tools.handleSearchParam({
          vendorId: this.subLocation.vendorId,
          regionId: this.subLocation.region
        })
      }).then((data) => {
        if (data.success) {
          cell.vpcList = data.data.rows
          if (cell.vpcUuid) this.getSubnet(cell)
        }
      })
    },
    getSgroupList(cell, isInit = false) {
      if (this.disabled || this.subLocation.vendorType !== 'CECSTACK' || !this.subLocation.vendorId || !this.subLocation.region) return
      getGroup({
        page: 1,
        rows: 9999,
        params: this.$tools.handleSearchParam({
          vendorId: this.subLocation.vendorId,
          regionId: this.subLocation.region
        })
      }).then((data) => {
        if (data.success) {
          cell.groupList = data.data.rows
        }
      })
    },
    changeVPC(cell) {
      cell.subnetUuid = ''
      this.getSubnet(cell)
    },
    // 获取子网
    getSubnet(cell) {
      const vpcUuid = cell.vpcUuid
      getSubnet({
        simple: true,
        params: JSON.stringify([
          {
            param: {
              vpcUuid,
              zone: this.subLocation.az,
              vendorId: this.subLocation.vendorId
            },
            sign: 'EQ'
          }
        ])
      }).then((data) => {
        if (data.success) {
          cell.vpcList.map((i) => {
            cell.subnetList = data.data.rows
          })
        }
      })
    },
    getIp(obj, isInit = false) {
      if (this.disabled) return
      const findIppool = this.ippools.find(({ ipPoolId }) => ipPoolId === obj.ipPoolId) || {}
      obj.ipPoolName = findIppool.ipPoolName
      obj.portGroupId = findIppool.portGroupId || ''
      if (obj.ipPolicy != 'Manual' || !obj.ipPoolId) {
        obj.address = []
        return
      }
      this.$set(obj, 'loading', true)
      conditionIp({ condition: JSON.stringify({ condition: 'listByPoolAndStatus', poolId: obj.ipPoolId, status: 'free' }) })
        .then((data) => {
          if (data.success) {
            // 空闲的所有 ip
            // Vue 禁止响应式
            const freezeAllIps = Object.freeze(uniq([...(this.prefixNodeIps[obj.ipPoolId] || []), ...data.data.map(({ ip }) => ip)]))
            // 上一节点的虽然锁定,但是也是可选
            this.$set(findIppool, 'freezeAllIps', freezeAllIps)
            // 校验数量
            if (freezeAllIps.length) {
              const address = []
              freezeAllIps.forEach((ip) => {
                if (address.length === this.count) return
                if (isInit) {
                  // 审批回显初始化
                  address.push(...obj.address)
                } else if (obj.address.includes(ip) || !this.selectedIps.includes(ip)) {
                  // 原本就在里面 || 没被使用过
                  address.push(ip)
                }
              })
              obj.address = address
              this.$set(obj, 'showIps', freezeAllIps.slice(0, 20))
            } else {
              this.$message.warning('可用 IP 数量不足')
              obj.address = []
              obj.ipPoolId = ''
              obj.portGroupId = ''
              obj.ipPolicy = 'Manual'
            }
          }
        })
        .catch(() => {
          this.$message.warning('获取 IP 失败')
          obj.address = []
          obj.ipPolicy = 'Auto'
        })
        .finally(() => (obj.loading = false))
    },
    getIpPool(manual) {
      if (manual) {
        // 切换资源池回显
        this.configs.networkCardConfigs.map((item) => {
          item.ipPoolId = ''
        })
      }
      this.ippools = []
      this.dialog.row.networkRelations.forEach((item) => {
        if (item.version == 'V4') this.ippools.push(cloneDeep(item))
      })
    },
    handleSubmit() {
      this.$refs.addData.validate((valid) => {
        if (valid) {
          if (this.configs.networkCardConfigs.some((item) => item.loading)) return this.$message.warning('请等待 IP 获取完成')
          if (this.configs.networkCardConfigs.some((item) => item.ipPolicy === 'Manual' && !item.address?.length)) return this.$message.warning('手动模式请选择 IP')
          if (typeof this.dialog.cb === 'function') this.dialog.cb()
          this.dialog.visible = false
        }
      })
    }
  }
}
</script>
