<template>
  <div>
    <el-popover
      :visible="state.show"
      placement="bottom"
      trigger="click"
      :popper-style="{
        padding: 0,
        minWidth: 0,
        width: '360px',
      }"
    >
      <template #reference>
        <div
          @click="() => (state.show = !state.show)"
          class="bg __hover-bg flex h-8 w-full items-center justify-end rounded-sm px-2 text-xs"
        >
          <img
            v-if="modelConfig?.modelId"
            src="@/assets/images/model/model-default-logo.png"
            class="mr-2 size-4"
          />
          <span v-title class="mr-auto text-xs opacity-65">
            {{ modelConfig?.modelId ? modelConfig?.modelName : '请选择模型' }}
          </span>
          <el-popover
            :visible="state.showConfig"
            placement="bottom"
            trigger="click"
            :popper-style="{
              padding: 0,
              minWidth: 0,
              width: '360px',
            }"
          >
            <template #reference>
              <SvgIcon
                name="config"
                size="16"
                rotate="90"
                color="#33333377"
                class="__hover mr-2"
                @click.stop="() => (state.showConfig = !state.showConfig)"
              />
            </template>
            <div class="px-2 py-3" :model-select-config-popover="true">
              <div class="text-sm font-bold">参数</div>
              <template v-for="item in state.configOptions">
                <div class="mt-1 flex items-center">
                  <a-switch
                    v-model:checked="state.modelConfig.paramsConfig[item.isKey]"
                    size="small"
                    :checkedValue="1"
                    :unCheckedValue="0"
                  ></a-switch>
                  <span class="ml-1 flex w-20 items-center text-sm">
                    {{ item.label }}
                    <el-tooltip :content="item.tips" placement="top">
                      <SvgIcon name="czr_tip" size="14" class="ml-1" />
                    </el-tooltip>
                  </span>
                  <a-row class="ml-auto flex-1" justify="end">
                    <a-col :span="12" class="mr-2">
                      <a-slider
                        v-model:value="
                          state.modelConfig.paramsConfig[item.valueKey]
                        "
                        :min="item.min"
                        :max="item.max"
                        :step="item.step"
                        :disabled="!state.modelConfig.paramsConfig[item.isKey]"
                      />
                    </a-col>
                    <a-col :span="8">
                      <a-input-number
                        v-model:value="
                          state.modelConfig.paramsConfig[item.valueKey]
                        "
                        :min="item.min"
                        :max="item.max"
                        :step="item.step"
                        :disabled="!state.modelConfig.paramsConfig[item.isKey]"
                        style="width: 100%"
                      />
                    </a-col>
                  </a-row>
                </div>
              </template>
              <div class="mt-1 flex justify-between">
                <div class="text-xs">
                  <div class="flex items-center">
                    停止序列
                    <el-tooltip
                      content="最多四个序列，API 将停止生成更多的token。返回的文本将不包含停止序列。"
                      placement="top"
                    >
                      <SvgIcon name="czr_tip" size="14" class="ml-1" />
                    </el-tooltip>
                  </div>
                  <div>输入序列并按Enter键</div>
                </div>
                <div class="bg ml-8 w-full flex-1 rounded-sm p-2 text-xs">
                  <div class="flex flex-wrap gap-1">
                    <template
                      v-for="(item, index) in state.modelConfig.paramsConfig
                        .stopSequence"
                    >
                      <div
                        class="flex items-center gap-1 rounded-sm border border-gray-300 p-1"
                      >
                        <div class="flex-1 text-justify">
                          {{ item }}
                        </div>
                        <SvgIcon
                          class="__hover"
                          name="czr_close_1"
                          size="10"
                          @click="
                            state.modelConfig.paramsConfig.stopSequence.splice(
                              index,
                              1,
                            )
                          "
                        />
                      </div>
                    </template>
                  </div>
                  <div class="mt-1">
                    <a-input
                      v-model:value="state.stopText"
                      size="small"
                      :maxlength="20"
                      placeholder="输入序列并按 Enter 键"
                      @pressEnter="
                        (e) =>
                          state.stopText.trim()
                            ? (state.modelConfig.paramsConfig.stopSequence.push(
                                state.stopText,
                              ),
                              (state.stopText = ''))
                            : undefined
                      "
                    />
                  </div>
                </div>
              </div>
            </div>
          </el-popover>
          <SvgIcon name="czr_arrow" size="12" rotate="90" color="#33333377" />
        </div>
      </template>
      <div class="" :model-select-popover="true">
        <div class="filter">
          <el-input
            v-model="state.text"
            :prefix-icon="Search"
            placeholder="搜索变量"
            clearable
          />
        </div>
        <div class="flex flex-col p-1">
          <template v-for="item in optionsCpt">
            <div
              class="__hover-bg flex items-center px-2 py-2"
              @click="onModel(item)"
            >
              <img
                src="@/assets/images/model/model-default-logo.png"
                class="mr-2 size-4"
              />
              {{ item.name }}
            </div>
          </template>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script setup lang="ts">
import { computed, onBeforeMount, onMounted, reactive, watch } from 'vue'
import { domRootHasAttr } from '@/utils/czr-util'
import { pluginGetInstanceList } from '@/api/modules/model'
import { Search } from '@element-plus/icons-vue'
import SvgIcon from '@/components/SvgIcon/index.vue'

const emit = defineEmits(['update:modelConfig'])
const props = defineProps({
  type: { required: true },
  modelConfig: {},
})
const state: any = reactive({
  modelConfig: props.modelConfig,
  show: false,
  showConfig: false,
  options: [],
  text: '',
  stopText: '',
  configOptions: [
    {
      label: '温度',
      tips: '核采样阈值。用于决定结果随机性，取值越高随机性越强即相同的问题得到的不同答案的可能性越高。',
      isKey: 'isTemperature',
      is: 1,
      valueKey: 'temperature',
      value: 0.7,
      max: 2,
      min: 0,
      step: 0.1,
    },
    {
      label: 'Top P',
      tips: '生成过程中核采样方法概率阈值。取值越大，生成的随机性越高；取值越小，生成的确定性越高。',
      isKey: 'isTopP',
      valueKey: 'topP',
      value: 1,
      max: 1,
      min: 0,
      step: 0.1,
    },
    {
      label: '频率惩罚',
      tips: '用于控制模型已使用字词的重复率。 提高此项可以降低模型在输出中重复相同字词的重复度。',
      isKey: 'isFrequency',
      valueKey: 'frequency',
      value: 0,
      max: 2,
      min: -2,
      step: 0.1,
    },
    {
      label: '存在惩罚',
      tips: '用于控制模型生成时的重复度。提高此项可以降低模型生成的重复度。',
      isKey: 'isExist',
      valueKey: 'exist',
      value: 0,
      max: 2,
      min: -2,
      step: 0.1,
    },
    {
      label: '最大标记',
      tips: '模型回答的tokens的最大长度。',
      isKey: 'isTokens',
      valueKey: 'tokens',
      value: 512,
      max: 4096,
      min: 1,
      step: 1,
    },
  ],
})
watch(
  () => props.modelConfig,
  (n) => {
    reset()
  },
)
const reset = () => {
  if (props.modelConfig) {
    state.modelConfig = props.modelConfig
  } else {
    state.modelConfig = {
      modelId: '',
      modelName: '',
      paramsConfig: {
        stopSequence: [],
      },
    }
    state.configOptions.forEach((v) => {
      state.modelConfig.paramsConfig[v.isKey] = v.is
      state.modelConfig.paramsConfig[v.valueKey] = v.value
    })
  }
}
watch(
  () => state.modelConfig,
  (n) => {
    emit('update:modelConfig', n)
  },
  { deep: true },
)
const optionsCpt = computed(() => {
  if (!state.text) {
    return state.options
  }
  return state.options
    .map((v) => {
      const obj = { ...v }
      obj.options = obj.options.filter(
        (s) => s.label.includes(state.text) || s.key.includes(state.text),
      )
      return obj
    })
    .filter((v) => v.options.length > 0)
})
const onModel = (row) => {
  state.modelConfig.modelId = row.id
  state.modelConfig.modelName = row.name
  state.show = false
}
const onMouseDown = (e) => {
  if (!domRootHasAttr(e.target, 'model-select-popover')) {
    state.show = false
  }
}
watch(
  () => state.show,
  (n) => {
    if (n) {
      document.addEventListener('mousedown', onMouseDown)
    } else {
      document.removeEventListener('mousedown', onMouseDown)
    }
  },
  { immediate: true },
)
const onConfigMouseDown = (e) => {
  if (!domRootHasAttr(e.target, 'model-select-config-popover')) {
    state.showConfig = false
  }
}
watch(
  () => state.showConfig,
  (n) => {
    if (n) {
      document.addEventListener('mousedown', onConfigMouseDown)
    } else {
      document.removeEventListener('mousedown', onConfigMouseDown)
    }
  },
  { immediate: true },
)
onMounted(() => {
  if (state.options.length === 0) {
    pluginGetInstanceList({
      page: 1,
      size: 100000,
      modeType: props.type,
      status: 1,
    }).then(({ data }: any) => {
      state.options = data.records
    })
  }
})
onBeforeMount(() => {
  reset()
})
</script>

<style lang="scss" scoped>
@use '@/views/workflow/instance/component/style';

.bg {
  background-color: style.$inputBg;
}
.vars-display {
  //border: style.$borderStyle;
  width: 100%;
  height: 32px;
  padding: 0 8px;
  border-radius: 4px;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  position: relative;
  background-color: style.$inputBg;
  .del {
    position: absolute;
    right: 0;
    width: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
.filter {
  padding: 10px;
  border-bottom: style.$borderStyle;
}
</style>
