<template>
  <div class="mod-prod-sku-tag">
    <!-- 商品规格表单项 -->
    <el-form-item label="商品规格">
      <!-- 添加规格按钮 -->
      <el-button @click="shopTagInput()">
        添加规格
      </el-button>

      <!-- 遍历skuTags数组，显示每个规格及其值 -->
      <div v-for="(tag, tagIndex) in skuTags" :key="tagIndex">
        <!-- 显示规格名称 -->
        <span>{{ tag.tagName }}</span>

        <!-- 删除规格按钮 -->
        <el-button
          class="button-new-tag"
          type="text"
          icon="el-icon-delete"
          @click="removeTag(tagIndex)"
        >
          删除
        </el-button>
        <br>

        <!-- 遍历当前规格下的所有值，并以标签形式展示 -->
        <el-tag
          v-for="(tagItem, tagItemIndex) in tag.tagItems"
          :key="tagItem.valueId"
          closable
          :disable-transitions="false"
          @close="handleTagClose(tagIndex, tagItemIndex)"
        >
          {{ tagItem.propValue }}
        </el-tag>

        <!-- 如果显示输入框，则渲染一个用于新增规格值的输入框 -->
        <el-input
          v-if="tagItemInputs[tagIndex] && tagItemInputs[tagIndex].visible"
          :ref="`saveTagInput${tagIndex}`"
          v-model="tagItemInputs[tagIndex].value"
          class="input-new-tag"
          @keyup.enter="handleInputConfirm(tagIndex)"
          @blur="handleInputConfirm(tagIndex)"
        />

        <!-- 否则，显示“+ 添加”按钮以切换到输入框 -->
        <el-button
          v-else
          class="button-new-tag"
          @click="showTagInput(tagIndex)"
        >
          + 添加
        </el-button>
      </div>
    </el-form-item>

    <!-- 当isShowTagInput为true时显示规格名选择项 -->
    <el-form-item v-show="isShowTagInput" label="规格名">
      <el-col :span="8">
        <!-- 规格名选择器，允许创建新选项 -->
        <el-select
          v-model="addTagInput.propName"
          filterable
          allow-create
          default-first-option
          placeholder="请选择"
          @change="handleTagClick"
        >
          <!-- 遍历未使用的规格，作为选择器的选项 -->
          <el-option
            v-for="item in unUseTags"
            :key="item.propId"
            :label="item.propName"
            :value="item.propName"
          />
        </el-select>
      </el-col>
    </el-form-item>

    <!-- 当isShowTagInput为true时显示规格值选择项 -->
    <el-form-item v-show="isShowTagInput" label="规格值">
      <el-col :span="8">
        <!-- 规格值选择器，支持多选并允许创建新选项 -->
        <el-select
          v-model="addTagInput.selectValues"
          multiple
          filterable
          allow-create
          default-first-option
          placeholder="请选择"
        >
          <!-- 遍历数据库中的规格值，作为选择器的选项 -->
          <el-option
            v-for="item in dbTagValues"
            :key="item.valueId"
            :label="item.propValue"
            :value="item.propValue"
          />
        </el-select>
      </el-col>
    </el-form-item>

    <!-- 操作按钮组，当isShowTagInput为true时显示 -->
    <el-form-item>
      <!-- 确认按钮，点击后调用addTag方法 -->
      <el-button
        v-show="isShowTagInput"
        type="primary"
        @click="addTag()"
      >
        确定
      </el-button>

      <!-- 取消按钮，点击后隐藏规格名/值输入框 -->
      <el-button
        v-show="isShowTagInput"
        @click="hideTagInput()"
      >
        取消
      </el-button>
    </el-form-item>
  </div>
</template>

<script setup>
import { ElMessage } from 'element-plus'
import { scoreProdStore } from '@/stores/prod.js'
import { ref, computed, watch, onMounted, nextTick } from 'vue'

// 获取全局状态存储实例
const prod = scoreProdStore()

// 定义props接收父组件传递的数据
const props = defineProps({
  skuList: {
    type: Array,
    default: () => []
  }
})

// 定义emits用于更新父组件的数据
const emit = defineEmits(['change'])

// 管理标签输入框显示/隐藏的状态
const isShowTagInput = ref(false)

// 新增标签时的输入数据模型
const addTagInput = ref({
  propName: '', // 规格名
  selectValues: [] // 规格值数组
})

// 类型标记，用于区分不同的操作类型（如添加或删除）
const type = ref(0)

// 当前标签项名称引用
const tagItemName = ref('')

// 标签项输入框数组
const tagItemInputs = ref([])

// 数据库中的规格值引用
const dbTagValues = ref([])

// 数据库中的规格引用
const dbTags = ref([])

// 变量初始化
let tagName = ''
let tagNameIndex = 0
let maxValueId = 0 // 规格值id最大
let maxPropId = 0 // 规格id 最大
let initing = false

// 计算属性：获取并设置SKU标签
const skuTags = computed({
  get () { return prod.skuTags },
  set (val) { prod.updateSkuTags(val) }
})

/**
 * 未使用的规格, 通过计算属性计算
 */
const unUseTags = computed(() => {
  const res = []
  for (let i = 0; i < dbTags.value.length; i++) {
    const dbTag = dbTags.value[i]
    const specIndex = skuTags.value?.findIndex(tag => tag.tagName === dbTag.propName)
    if (specIndex === -1) {
      res.push(dbTag)
    }
  }
  return res
})

// 默认SKU计算属性
const defalutSku = computed(() => prod.defalutSku)

// 监听skuTags变化，更新SKU列表
watch(() => skuTags.value,
  (val) => {
    if (initing) {
      initing = false
      return
    }
    let skuListArr = []

    // 根据type的不同处理SKU列表的变化
    if (type.value === 4) {
      // 删除规格值
      props.skuList?.forEach(sku => {
        const propertiesArray = sku.properties.split(';')
        if (tagItemName.value !== propertiesArray[tagNameIndex].split(':')[1]) {
          skuListArr.push(sku)
        }
      })
    } else if (type.value === 2) {
      // 添加规格值
      const properties = `${tagName}:${tagItemName.value}`
      // 增加或删除规格
      let tempSkuList = []
      val?.forEach(tag => {
        if (skuListArr.length === 0) {
          if (tagName === tag.tagName) {
            const sku = Object.assign({}, defalutSku.value)
            sku.properties = properties
            skuListArr.push(sku)
          } else {
            tag.tagItems.forEach(tagItem => {
              const sku = Object.assign({}, defalutSku.value)
              sku.properties = `${tag.tagName}:${tagItem.propValue}`
              skuListArr.push(sku)
            })
          }
          if (val.length === 1) {
            skuListArr = props.skuList.concat(skuListArr)
          }
        } else {
          tempSkuList = []
          if (tagName === tag.tagName) {
            skuListArr.forEach(sku => {
              if (sku.properties.indexOf(tagName) === -1) {
                const newSku = Object.assign({}, sku)
                newSku.properties = `${sku.properties};${properties}`
                tempSkuList.push(newSku)
              }
            })
          } else {
            tag.tagItems.forEach(tagItem => {
              skuListArr.forEach(sku => {
                if (sku.properties.indexOf(tag.tagName) === -1) {
                  const newSku = Object.assign({}, sku)
                  newSku.properties = `${sku.properties};${tag.tagName}:${tagItem.propValue}`
                  tempSkuList.push(newSku)
                }
              })
            })
          }
          skuListArr = props.skuList.concat(tempSkuList)
        }
      })
    } else {
      // 增加或删除规格
      let tempSkuList = []
      val?.forEach(tag => {
        if (skuListArr.length === 0) {
          tag.tagItems.forEach(tagItem => {
            const sku = Object.assign({}, defalutSku.value)
            sku.properties = `${tag.tagName}:${tagItem.propValue}`
            skuListArr.push(sku)
          })
        } else {
          tempSkuList = []
          tag.tagItems.forEach(tagItem => {
            skuListArr.forEach(sku => {
              const newSku = Object.assign({}, sku)
              newSku.properties = `${sku.properties};${tag.tagName}:${tagItem.propValue}`
              tempSkuList.push(newSku)
            })
          })
          skuListArr = tempSkuList
        }
      })
    }

    // 如果没有生成任何SKU，则添加一个默认SKU
    if (!skuListArr.length) {
      skuListArr.push(Object.assign({}, defalutSku.value))
    }

    // 更新父组件的SKU列表
    emit('change', skuListArr)
  }, {
    deep: true
  })

// 组件挂载时初始化
onMounted(() => {
  // 获取所有规格列表
  http({
    url: http.adornUrl('/prod/spec/list'),
    method: 'get',
    params: http.adornParams()
  }).then(({ data }) => {
    dbTags.value = data
    if (data) {
      maxPropId = Math.max.apply(Math, data.map(item => item.propId))
    } else {
      maxPropId = 0
    }
  })

  // 获取最大的规格值ID
  http({
    url: http.adornUrl('/prod/spec/listSpecMaxValueId'),
    method: 'get',
    params: http.adornParams()
  }).then(({ data }) => {
    if (data) {
      maxValueId = data
    } else {
      maxValueId = 0
    }
  })
})

/**
 * 初始化SKU标签和列表
 * @param {Array} skuList - SKU列表
 */
const init = (skuList) => {
  if (!skuList || !skuList.length) {
    skuTags.value = []
    emit('change', [Object.assign({}, defalutSku.value)])
    return
  }
  initing = true
  const skuTagsParam = []
  for (let i = 0; i < skuList.length; i++) {
    const sku = skuList[i]
    if (!sku.properties) break
    const propertiesArray = sku.properties.split(';')
    for (const j in propertiesArray) {
      const properties = propertiesArray[j].split(':')
      if (!skuTagsParam[j]) {
        skuTagsParam[j] = {
          tagName: properties[0],
          tagItems: []
        }
        tagItemInputs.value.push({ visible: false, value: '' })
      }
      const tagItemNameIndex = skuTagsParam[j].tagItems.findIndex((tagItemName) => tagItemName.propValue === properties[1])
      if (tagItemNameIndex === -1) {
        skuTagsParam[j].tagItems.push({ propValue: properties[1] })
      }
    }
  }
  skuTags.value = skuTagsParam
}
defineExpose({ init })

/**
 * 显示规格名、规格值输入框
 */
const shopTagInput = () => {
  isShowTagInput.value = true
}

/**
 * 隐藏规格名、规格值输入框，并清除内容
 */
const hideTagInput = () => {
  isShowTagInput.value = false
  cleanTagInput()
}

/**
 * 添加新的规格和规格值
 */
const addTag = () => {
  const selectValues = addTagInput.value.selectValues
  if (!addTagInput.value.propName) {
    ElMessage.error('请输入规格名')
    return
  }
  if (!selectValues.length) {
    ElMessage.error('请输入规格值')
    return
  }
  isShowTagInput.value = false
  for (let i = 0; i < selectValues.length; i++) {
    const element = selectValues[i]
    const is = Object.prototype.toString.call(element) === '[object Object]'
    if (!is) {
      maxPropId = maxPropId + 1
      break
    }
  }
  const tagItems = []
  for (let i = 0; i < selectValues.length; i++) {
    const element = selectValues[i]
    const is = Object.prototype.toString.call(element) === '[object Object]'
    if (is) {
      tagItems.push(element)
    } else {
      maxValueId = maxValueId + 1
      tagItems.push({ propId: maxPropId, propValue: element, valueId: maxValueId })
    }
  }
  // 向规格中放入规格输入框内的数据
  prod.addSkuTag({
    tagName: addTagInput.value.propName,
    tagItems
  })
  type.value = 1
  cleanTagInput()
}

/**
 * 清除规格值输入框内容
 */
const cleanTagInput = () => {
  addTagInput.value = {
    propName: '',
    selectValues: []
  }
  dbTagValues.value = []
}

/**
 * 规格名输入框，选中规格事件
 */
const handleTagClick = () => {
  // 清空规格值输入框
  dbTagValues.value = []
  addTagInput.value.selectValues = []
  // 判断规格名输入的值是否为数据库中已有的值
  const specsIndex = dbTags.value?.findIndex(spec => spec.propName === addTagInput.value.propName)
  // 如果不是，则说明为用户随便输入
  if (specsIndex === -1) return
  // 如果数据库已有该规格名，则获取根据id获取该规格名称含有的规格值
  http({
    url: http.adornUrl(`/prod/spec/listSpecValue/${dbTags.value[specsIndex].propId}`),
    method: 'get',
    params: http.adornParams()
  }).then(({ data }) => {
    dbTagValues.value = data
  })
}

/**
 * 删除规格值
 * @param {number} tagIndex - 标签索引
 * @param {number} tagItemIndex - 标签项索引
 */
const handleTagClose = (tagIndex, tagItemIndex) => {
  tagName = skuTags.value[tagIndex].tagName
  tagNameIndex = tagIndex
  tagItemName.value = skuTags.value[tagIndex].tagItems[tagItemIndex].propValue
  if (skuTags.value[tagIndex].tagItems.length === 1) {
    return
  }
  type.value = 4
  prod.removeSkuTagItem(tagIndex, tagItemIndex)
}

/**
 * 标签输入框确定时调用
 * @param {number} tagIndex - 标签索引
 */
const handleInputConfirm = (tagIndex) => {
  if (checkTagItem(tagIndex)) {
    return
  }
  const tagItems = skuTags.value[tagIndex].tagItems
  const itemValue = tagItemInputs.value[tagIndex].value
  const index = tagItems.length - 1
  tagName = skuTags.value[tagIndex].tagName
  tagItemName.value = tagItemInputs.value[tagIndex].value
  const maxValue = getMaxValueId(skuTags.value[tagIndex].tagItems)
  const tagItem = { propId: index === -1 ? 0 : skuTags.value[tagIndex].tagItems[index].propId, propValue: itemValue, valueId: index === -1 ? 0 : (maxValue + 1) }
  if (tagItem) {
    prod.addSkuTagItem({ tagIndex, tagItem })
  }
  tagItemInputs.value[tagIndex].visible = false
  tagItemInputs.value[tagIndex].value = ''
  type.value = 2
}

/**
 * 显示标签输入框
 * @param {number} tagIndex - 标签索引
 */
const showTagInput = (tagIndex) => {
  tagItemInputs.value.push({ visible: false, value: '' })
  tagItemInputs.value[tagIndex].visible = true
  nextTick(() => {
    [`saveTagInput${tagIndex}`][0].value.input.focus()
  })
}

/**
 * 获取数据集合所有对象中某个属性的最大值
 * @param {Array} list - 对象数组
 * @returns {number} 最大值
 */
const getMaxValueId = (list) => {
  return Math.max.apply(Math, list.map(item => item.valueId))
}

/**
 * 删除 规格
 * @param {number} tagIndex - 标签索引
 */
const removeTag = (tagIndex) => {
  type.value = 3
  prod.removeSkuTag(tagIndex)
}

/**
 * 新增规格值时，判断是否存在同名的规格值
 * @param {number} tagIndex - 标签索引
 * @returns {boolean} 是否存在重复
 */
const checkTagItem = (tagIndex) => {
  const tagItem = tagItemInputs.value[tagIndex].value
  if (!tagItem) {
    tagItemInputs.value[tagIndex].visible = false
    tagItemInputs.value[tagIndex].value = ''
    return true
  }
  let isSame = false
  skuTags.value?.forEach(tag => {
    const arr = tag.tagItems.map((item) => {
      return item.propValue
    })
    if (arr.indexOf(tagItem) > -1) {
      isSame = true
      ElMessage.error('product.specificationValue') // 这里可能需要替换为实际的错误消息
      return false
    }
  })
  return isSame
}
</script>

<style lang="scss" scoped>
.mod-prod-sku-tag {
  // 定义el-tag之间的间距
  :deep(.el-tag + .el-tag) {
    margin-left: 10px; // 设置相邻标签的左间距
  }

  // 新增标签按钮的样式
  .button-new-tag {
    margin-left: 10px; // 设置新增标签按钮与前一个元素的左间距
    height: 32px; // 设置按钮高度
    line-height: 30px; // 设置行高以垂直居中文字
    padding-top: 0; // 移除顶部内边距
    padding-bottom: 0; // 移除底部内边距
  }

  // 新增标签输入框的样式
  .input-new-tag {
    width: 90px; // 设置输入框宽度
    margin-left: 10px; // 设置输入框左间距
    vertical-align: bottom; // 设置垂直对齐方式为底部对齐
  }
}

// 新增规格外部边框样式
:deep(.sku-border) {
  border: 1px solid #EBEEF5; // 设置边框颜色和粗细
  width: 70%; // 设置宽度占父容器的比例
}

// SKU背景样式
:deep(.sku-background) {
  background-color: #F6f6f6; // 设置背景颜色
  margin: 12px 12px; // 设置外边距

  // 修改按钮样式
  .el-button {
    margin-left: 10px; // 设置按钮左间距

    span {
      color: #000 !important; // 强制设置按钮文字颜色为黑色
    }
  }

  // 修改表单项标签样式
  .el-form-item__label {
    padding: 0 24px 0 0; // 调整表单项标签的内边距
  }
}

// SKU标签样式
:deep(.sku-tag) {
  margin: 12px 12px; // 设置标签的外边距
}

// 标签树样式
:deep(.tagTree) {
  margin-left: 18px; // 设置标签树的左间距
  padding-bottom: 8px; // 设置标签树底部的内边距
}

// 表单项内容中的div样式
.el-form-item__content div {
  width: 100%; // 设置div的宽度为100%，确保其占据整个表单项内容区域
}
</style>
