<script setup lang="ts">
import { h, ref, shallowRef, useTemplateRef, watch, watchEffect } from 'vue'
import fetchEventStreamSource from './utils/fetch-event-stream-source'
import type { ResponseData } from './utils/fetch-event-stream-source'
import type { Editor } from 'tinymce'
import type { DropdownGroupOption, DropdownOption, NDropdown } from 'naive-ui'
import type { VNode } from 'vue'
import { useI18n } from 'vue-i18n'
import MarkdownRender from '@/components/markdown-render/markdown-render.vue'

interface Props {
  editor: Editor | null
  locationInfo: {
    position: 'top' | 'middle' | 'bottom'
    positionValue: string
  }
}

const props = defineProps<Props>()

const isShowModal = defineModel<boolean>('isShowModal', { required: true })

const { t } = useI18n()
const toneSelectRef = useTemplateRef<InstanceType<typeof NDropdown>>('toneSelectRef')
const contentOptimizationEditMRRef = useTemplateRef<InstanceType<typeof MarkdownRender>>('contentOptimizationEditMRRef')

const containerWrapperStyle = ref<{ top?: string; bottom?: string; transform?: string }>({})
const questionContent = ref('')

const contentEditStatus = ref<'Normal' | 'Editing' | 'Response'>('Normal')
const isShowEditSelectToolbar = ref(true)
const isShowReplaceToolbar = ref(false)
const editResponseContent = ref('')
const editResponseLoading = ref(false)

const controller = shallowRef<AbortController | null>(null)
const toneList = ref([
  { key: 'Colloquial', label: t('editor_module.colloquial') },
  { key: 'Academicization', label: t('editor_module.academicization') },
  { key: 'HumorousAndVivid', label: t('editor_module.humorous_and_vivid') },
  { key: 'SeriousAndFormal', label: t('editor_module.serious_and_formal') },
  { key: 'ConciseAndClear', label: t('editor_module.concise_and_clear') },
  { key: 'ElegantLiteraryStyle', label: t('editor_module.elegant_literary_style') },
])

watch(
  () => isShowModal.value,
  (newValue) => {
    if (newValue) {
      contentEditStatus.value = 'Editing'
    } else {
      contentEditStatus.value = 'Normal'
      questionContent.value = ''

      if (controller.value) {
        controller.value.abort()
        controller.value = null
      }
    }
  },
)

watch(questionContent, (newValue) => {
  if (newValue) {
    isShowEditSelectToolbar.value = false
  } else {
    isShowEditSelectToolbar.value = true
  }
})

watchEffect(() => {
  if (props.locationInfo.position === 'bottom') {
    containerWrapperStyle.value = { bottom: props.locationInfo.positionValue, top: 'unset' }
  } else if (props.locationInfo.position === 'top') {
    containerWrapperStyle.value = { top: props.locationInfo.positionValue }
  } else {
    containerWrapperStyle.value = { top: props.locationInfo.positionValue, transform: 'translateY(-100%)' }
  }
})

function editResponseStatusReset() {
  editResponseContent.value = ''
  editResponseLoading.value = true
  isShowReplaceToolbar.value = false

  contentEditStatus.value = 'Response'
}

function fetchContentOptimize(url: string, questionContentStr: string = '') {
  const selectContent = props.editor?.selection.getContent()

  editResponseStatusReset()

  controller.value = fetchEventStreamSource(
    url,
    {
      articleContent: selectContent || '',
      editorRequired: questionContentStr || '',
    },
    {
      onopen: async () => {
        questionContent.value = ''
      },
      onResponse: (res: ResponseData) => {
        editResponseContent.value += res.message
      },
      onend: () => {
        editResponseLoading.value = false
        isShowReplaceToolbar.value = true
      },
    },
  )
}

function handleQuestionSubmitEnter(event: KeyboardEvent) {
  if (event.key === 'Enter' && !event.shiftKey) {
    event.preventDefault()

    fetchContentOptimize('/aiGcRest/articleRewrite.json', questionContent.value)
  }
}

function handleRetouching() {
  // 润色
  fetchContentOptimize('/aiGcRest/articlePolish.json', questionContent.value)
}
function handleExpansion() {
  // 扩写
  fetchContentOptimize('/aiGcRest/articleExpand.json', questionContent.value)
}
function handleAbbreviation() {
  // 缩写
  fetchContentOptimize('/aiGcRest/articleRefine.json', questionContent.value)
}

function handleReplaceContent() {
  if (props.editor) {
    props.editor.selection.setContent(
      contentOptimizationEditMRRef.value?.getRenderTextContent() || editResponseContent.value,
    )

    contentEditStatus.value = 'Normal'
  }
}

function handleInsertContent() {
  const editor = props.editor

  if (editor) {
    editor.selection.collapse()
    editor.execCommand('mceInsertNewLine')
    editor.execCommand(
      'InsertHTML',
      false,
      contentOptimizationEditMRRef.value?.getRenderTextContent() || editResponseContent.value,
    )
    editor.execCommand('mceInsertNewLine')

    contentEditStatus.value = 'Normal'
  }
}

function handleEditResponseBreak() {
  contentEditStatus.value = 'Editing'
  questionContent.value = ''

  if (controller.value) {
    controller.value.abort()
    controller.value = null
  }
}

function handleToneSelect(_key: string, option: DropdownOption) {
  fetchContentOptimize('/aiGcRest/articleModifyTone.json', option.label as string)
}

function toneSelectMenuRenderOption({ node, option }: { node: VNode; option: DropdownOption | DropdownGroupOption }) {
  return h(
    'li',
    {
      class:
        'list-none select-none flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]',
      onClick: () => {
        if (node.children && Array.isArray(node.children) && node.children[0] && (node.children[0] as VNode).props) {
          ;(node.children[0] as VNode).props?.onClick()
        }
      },
    },
    [
      h('i', { class: 'iconfont icon-adjust-tone text-[16px] text-[#9ea3ff]' }, ''),
      h('span', { class: 'pl-[10px] text-[14px]' }, option.label as string),
    ],
  )
}
</script>

<template>
  <Transition mode="out-in">
    <div v-if="contentEditStatus === 'Editing'" class="absolute top-0 w-full px-[16px]" :style="containerWrapperStyle">
      <div class="relative rounded-[6px] bg-white py-[10px]">
        <n-input
          v-model:value="questionContent"
          size="large"
          type="textarea"
          :placeholder="t('editor_module.optimize_input_placeholder')"
          :autosize="{ minRows: 1, maxRows: 3 }"
          :allow-input="(value: string) => !value.startsWith(' ') && !value.endsWith(' ')"
          @keydown="handleQuestionSubmitEnter"
        >
          <template #prefix>
            <i class="iconfont icon-association text-theme-color"></i>
          </template>

          <template #suffix>
            <i
              class="iconfont icon-fasong text-[#d0ceff] transition"
              :class="{ 'text-theme-color': questionContent }"
            ></i>
          </template>
        </n-input>

        <Transition>
          <ul
            v-show="isShowEditSelectToolbar"
            class="absolute w-[142px] select-none overflow-hidden rounded-[5px] border border-[#9EA3FF] bg-white shadow-md"
            :class="
              locationInfo.position === 'bottom' ? 'top-[6px] -translate-y-full' : 'bottom-[6px] translate-y-full'
            "
          >
            <li
              class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
              @click="handleRetouching"
            >
              <i class="iconfont icon-retouching text-[16px] text-[#9ea3ff]"></i>
              <span class="pl-[10px] text-[14px]">{{ t('editor_module.retouching') }}</span>
            </li>
            <li
              class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
              @click="handleExpansion"
            >
              <i class="iconfont icon-expansion text-[16px] text-[#9ea3ff]"></i>
              <span class="pl-[10px] text-[14px]">{{ t('editor_module.expansion') }}</span>
            </li>
            <li
              class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
              @click="handleAbbreviation"
            >
              <i class="iconfont icon-suoxie text-[16px] text-[#9ea3ff]"></i>
              <span class="pl-[10px] text-[14px]">{{ t('editor_module.abbreviation') }}</span>
            </li>

            <n-dropdown
              ref="toneSelectRef"
              width="142"
              trigger="hover"
              class="!ml-[2px] overflow-hidden border border-[#9EA3FF] bg-white !p-0 !shadow-md"
              content-style="padding: 0;"
              :options="toneList"
              :placement="locationInfo.position === 'bottom' ? 'right-end' : 'right-start'"
              :render-option="toneSelectMenuRenderOption"
              @select="handleToneSelect"
            >
              <li
                class="flex h-[34px] cursor-pointer items-center px-[10px] transition-[background] duration-300 ease-linear hover:bg-[#eeeffe]"
              >
                <i class="iconfont icon-adjust-tone text-[16px] text-[#9ea3ff]"></i>
                <span class="pl-[10px] text-[14px]">{{ t('editor_module.adjust_the_tone') }}</span>
              </li>
            </n-dropdown>
          </ul>
        </Transition>
      </div>
    </div>
    <div v-else-if="contentEditStatus === 'Response'" class="absolute top-1/2 w-full -translate-y-1/2 px-[16px]">
      <div class="rounded-[5px] border border-[#9EA3FF] bg-white py-[14px] pl-[10px]">
        <div class="text-[14px] leading-[18px]">
          <n-scrollbar class="!max-h-[60vh]">
            <div class="pr-[10px]">
              <MarkdownRender
                ref="contentOptimizationEditMRRef"
                :raw-text-content="
                  editResponseContent || editResponseLoading
                    ? editResponseContent
                    : t('common_module.dialogue_module.empty_message_content')
                "
                color="#333"
              />
            </div>
          </n-scrollbar>
        </div>

        <Transition>
          <div v-show="editResponseLoading" class="flex select-none items-center justify-between pr-[10px]">
            <span>
              <template v-if="!editResponseContent">生成中...</template>
            </span>
            <i
              class="iconfont icon-tingzhi text-theme-color cursor-pointer text-[18px]"
              @click="handleEditResponseBreak"
            ></i>
          </div>
        </Transition>

        <Transition>
          <div v-show="isShowReplaceToolbar" class="mt-[9px] pr-[10px]">
            <n-button type="primary" size="small" @click="handleReplaceContent"
              >替换

              <template #icon>
                <i class="iconfont icon-tihuan"></i>
              </template>
            </n-button>

            <n-button class="!ml-[17px]" size="small" @click="handleInsertContent"
              >插入

              <template #icon>
                <i class="iconfont icon-charu"></i>
              </template>
            </n-button>
          </div>
        </Transition>
      </div>
    </div>
  </Transition>
</template>

<style lang="scss" scoped>
:deep(.n-input .n-input__state-border) {
  border-color: #9ea3ff !important;
}

.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>
