<script setup lang="ts">
import { nextTick, onMounted, ref, shallowRef, watch, watchEffect } from 'vue'
import SceneList from './components/scene-list.vue'
import TemplateMenu from './components/template-menu.vue'
import Quill from 'quill/core'
import 'quill/dist/quill.core.css'
import './formats/index'
import { getQuillOptions } from './quill-opstions'
import textStructureExtractor from './utils/text-structure-extractor'
import { Delta } from 'quill/core'
import type { TemplateMenuConfig } from '@/views/home/components/rich-text-input-box/data/template-menu'
import { debounce } from 'lodash-es'
import type { WorkModeType } from '@/views/home/components/rich-text-input-box/types/index'

interface Props {
  isQuestionSubmitBtnDisabled: boolean
  workMode: WorkModeType
}

const props = defineProps<Props>()

const emit = defineEmits<{
  submitQuestion: [question: string]
  workModeSwitch: [workMode: 'ApplicationMode' | 'SceneMode']
}>()

const questionContent = defineModel<string>('questionContent', { default: '' })
const currentSceneConfig = defineModel<{
  agentId: string
  agentTitle: string
  agentDesc: string
  agentAvatar: string
} | null>('currentSceneConfig', {
  default: null,
})
const editorModeEnable = defineModel<boolean>('editorModeEnable', { default: false })

const quillInst = shallowRef<Quill | null>(null)
const questionContentDraft = ref('')
const isInputFocus = ref(false)

const showSceneList = ref(false)
const showTemplateMenu = ref(false)

// const editorModeEnable = ref(false)

const onQuillTextChange = debounce((delta: Delta) => {
  const question = quillContentExtractor(delta)

  questionContentDraft.value = question.trim()
  questionContent.value = questionContentDraft.value
}, 100)

watch(
  () => currentSceneConfig.value,
  (newConfig) => {
    if (newConfig) {
      emit('workModeSwitch', 'SceneMode')

      nextTick(() => {
        quillInst.value?.focus()
      })
    }
  },
)

watch(
  () => questionContent.value,
  (newQuestion) => {
    if (newQuestion && newQuestion !== questionContentDraft.value) {
      if (quillInst.value) {
        quillInst.value.setContents([
          {
            insert: questionContent.value.trim() || '',
          },
        ])
      }
    }
  },
  { immediate: true },
)

watchEffect(() => {
  if (quillInst.value) {
    quillInst.value.on('text-change', onQuillTextChange)
  }
})

onMounted(() => {
  initQuill()
})

function initQuill() {
  quillInst.value = new Quill(
    '#rich-text-input-box-editor',
    getQuillOptions({
      keyboardCallback: {
        enter: () => {
          if (!props.isQuestionSubmitBtnDisabled) {
            handleQuestionSubmit()
          }
        },
        at: () => {
          showSceneList.value = true

          quillInst.value?.blur()
        },
      },
    }),
  )
}

function handleShowTemplateMenuSwitch() {
  nextTick(() => {
    if (!showTemplateMenu.value) {
      showTemplateMenu.value = true
    }
  })
}

function quillContentExtractor(delta: Delta) {
  const questionFragmentMap = new Map<number, string>()

  let templateInputPromptIndex = 0

  delta.forEach((op, opIndex) => {
    if (typeof op.insert === 'object' && op.insert['template-input-prompt']) {
      const promptEl = document.querySelector(
        `#rich-text-input-box-editor .template-input-prompt-container.prompt-index-${templateInputPromptIndex} .prompt-content`,
      )
      let promptContent = ''

      if (promptEl) {
        promptContent = promptEl.textContent || ''
      }

      questionFragmentMap.set(opIndex, promptContent)

      templateInputPromptIndex++
    } else {
      questionFragmentMap.set(opIndex, (op.insert as string) || '')
    }
  })

  let question = ''
  questionFragmentMap.forEach((fragment) => (question += fragment))

  return question
}

function handleQuestionSubmit() {
  if (quillInst.value) {
    const delta = quillInst.value.getContents()
    const question = quillContentExtractor(delta)

    emit('submitQuestion', question)

    questionContentDraft.value = ''
    questionContent.value = ''

    quillInst.value.setContents([])
  }
}

function onTemplateConfirm(templateConfig: TemplateMenuConfig['templateList'][0]) {
  const promptArr = textStructureExtractor(templateConfig.template || '')

  const delta = new Delta()

  let templateInputPromptIndex = 0

  promptArr.forEach((promptItem) => {
    if (promptItem.type === 'text') {
      delta.insert(promptItem.content)
    } else if (promptItem.type === 'placeholder') {
      delta.insert({
        'template-input-prompt': {
          placeholder: promptItem.content,
          index: templateInputPromptIndex,
        },
      })

      templateInputPromptIndex++
    }
  })

  quillInst.value?.setContents(delta)
}
</script>

<template>
  <SceneList v-model:show-scene-list="showSceneList" v-model:current-scene-config="currentSceneConfig" />
  <TemplateMenu v-model:show-template-menu="showTemplateMenu" @template-confirm="onTemplateConfirm" />

  <div
    class="hover:border-theme-color rounded-[5px] border border-[#9ea3ff] p-[12px] pr-0 transition duration-300"
    :class="{ 'shadow-[0_0_0_2px_rgba(0,13,255,0.2)]': isInputFocus }"
  >
    <n-scrollbar class="max-h-[140px]">
      <div class="pr-[12px]">
        <div id="rich-text-input-box-editor" class="font-['SourceHanSansCN-Regular'] text-[14px] text-[#333]"></div>
      </div>
    </n-scrollbar>

    <div class="mt-[8px] flex items-center justify-end px-[12px]">
      <Transition>
        <div v-show="workMode === 'SceneMode'" class="mr-[15px]">
          <n-tooltip trigger="hover">
            <template #trigger>
              <button
                class="mr-[5px] h-[24px] w-[32px] rounded-[5px] border border-[#333]/60 transition"
                :class="[showTemplateMenu ? 'border-[#9EA3FF] text-[#9EA3FF]' : '']"
                @click="handleShowTemplateMenuSwitch"
              >
                <i class="iconfont icon-moban1 text-[14px]"></i>
              </button>
            </template>
            模板
          </n-tooltip>

          <n-tooltip trigger="hover">
            <template #trigger>
              <button
                class="h-[24px] w-[32px] rounded-[5px] border border-[#333]/60 transition"
                :class="[editorModeEnable ? 'border-[#9EA3FF] text-[#9EA3FF]' : '']"
                @click="editorModeEnable = !editorModeEnable"
              >
                <i class="iconfont icon-wendangbianjiqi1 text-[14px]"></i>
              </button>
            </template>
            消息编辑器
          </n-tooltip>
        </div>
      </Transition>

      <div>
        <n-button type="primary" :disabled="isQuestionSubmitBtnDisabled" @click="handleQuestionSubmit">
          <i class="iconfont icon-send-icon"></i>
        </n-button>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
#rich-text-input-box-editor {
  :deep(.ql-editor) {
    padding: 0;
    overflow: hidden;
    line-height: 28px;
    overflow-wrap: break-word;

    &::before {
      left: 0;
    }
  }
}

.v-enter-active,
.v-leave-active {
  transition-timing-function: ease-in-out;
  transition-duration: 0.2s;
  transition-property: opacity;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
}
</style>
