'use client'
import type { FC } from 'react'
import type { ExternalDataTool } from '@/models/common'
import type { PromptRole, PromptVariable } from '@/models/debug'
import {
  RiDeleteBinLine,
  RiErrorWarningFill,
} from '@remixicon/react'
import { useBoolean } from 'ahooks'
import copy from 'copy-to-clipboard'
import { produce } from 'immer'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import { ADD_EXTERNAL_DATA_TOOL } from '@/app/components/app/configuration/config-var'
import Button from '@/app/components/base/button'
import {
  Copy,
  CopyCheck,
} from '@/app/components/base/icons/src/vender/line/files'
import PromptEditor from '@/app/components/base/prompt-editor'
import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
import { useToastContext } from '@/app/components/base/toast'
import Tooltip from '@/app/components/base/tooltip'
import ConfigContext from '@/context/debug-configuration'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { useModalContext } from '@/context/modal-context'
import { AppModeEnum } from '@/types/app'
import { cn } from '@/utils/classnames'
import { getNewVar, getVars } from '@/utils/var'
import ConfirmAddVar from './confirm-add-var'
import MessageTypeSelector from './message-type-selector'
import PromptEditorHeightResizeWrap from './prompt-editor-height-resize-wrap'
import s from './style.module.css'

type Props = {
  type: PromptRole
  isChatMode: boolean
  value: string
  onTypeChange: (value: PromptRole) => void
  onChange: (value: string) => void
  canDelete: boolean
  onDelete: () => void
  promptVariables: PromptVariable[]
  isContextMissing: boolean
  onHideContextMissingTip: () => void
  noResize?: boolean
}

const AdvancedPromptInput: FC<Props> = ({
  type,
  isChatMode,
  value,
  onChange,
  onTypeChange,
  canDelete,
  onDelete,
  promptVariables,
  isContextMissing,
  onHideContextMissingTip,
  noResize,
}) => {
  const { t } = useTranslation()
  const { eventEmitter } = useEventEmitterContextContext()

  const {
    mode,
    hasSetBlockStatus,
    modelConfig,
    setModelConfig,
    conversationHistoriesRole,
    showHistoryModal,
    dataSets,
    showSelectDataSet,
    externalDataToolsConfig,
  } = useContext(ConfigContext)
  const { notify } = useToastContext()
  const { setShowExternalDataToolModal } = useModalContext()
  const handleOpenExternalDataToolModal = () => {
    setShowExternalDataToolModal({
      payload: {},
      onSaveCallback: (newExternalDataTool?: ExternalDataTool) => {
        if (!newExternalDataTool)
          return
        eventEmitter?.emit({
          type: ADD_EXTERNAL_DATA_TOOL,
          payload: newExternalDataTool,
        } as any)
        eventEmitter?.emit({
          type: INSERT_VARIABLE_VALUE_BLOCK_COMMAND,
          payload: newExternalDataTool.variable,
        } as any)
      },
      onValidateBeforeSaveCallback: (newExternalDataTool: ExternalDataTool) => {
        for (let i = 0; i < promptVariables.length; i++) {
          if (promptVariables[i].key === newExternalDataTool.variable) {
            notify({ type: 'error', message: t('varKeyError.keyAlreadyExists', { ns: 'appDebug', key: promptVariables[i].key }) })
            return false
          }
        }

        return true
      },
    })
  }
  const isChatApp = mode !== AppModeEnum.COMPLETION
  const [isCopied, setIsCopied] = React.useState(false)

  const promptVariablesObj = (() => {
    const obj: Record<string, boolean> = {}
    promptVariables.forEach((item) => {
      obj[item.key] = true
    })
    return obj
  })()
  const [newPromptVariables, setNewPromptVariables] = React.useState<PromptVariable[]>(promptVariables)
  const [isShowConfirmAddVar, { setTrue: showConfirmAddVar, setFalse: hideConfirmAddVar }] = useBoolean(false)
  const handlePromptChange = (newValue: string) => {
    if (value === newValue)
      return
    onChange(newValue)
  }
  const handleBlur = () => {
    const keys = getVars(value)
    const newPromptVariables = keys.filter(key => !(key in promptVariablesObj) && !externalDataToolsConfig.find(item => item.variable === key)).map(key => getNewVar(key, ''))
    if (newPromptVariables.length > 0) {
      setNewPromptVariables(newPromptVariables)
      showConfirmAddVar()
    }
  }

  const handleAutoAdd = (isAdd: boolean) => {
    return () => {
      if (isAdd) {
        const newModelConfig = produce(modelConfig, (draft) => {
          draft.configs.prompt_variables = [...draft.configs.prompt_variables, ...newPromptVariables]
        })
        setModelConfig(newModelConfig)
      }
      hideConfirmAddVar()
    }
  }

  const minHeight = 102
  const [editorHeight, setEditorHeight] = React.useState(isChatMode ? 200 : 508)
  const contextMissing = (
    <div
      className="flex h-11 items-center justify-between rounded-tl-xl rounded-tr-xl pb-1 pl-4 pr-3 pt-2"
      style={{
        background: 'linear-gradient(180deg, #FEF0C7 0%, rgba(254, 240, 199, 0) 100%)',
      }}
    >
      <div className="flex items-center pr-2">
        <RiErrorWarningFill className="mr-1 h-4 w-4 text-[#F79009]" />
        <div className="text-[13px] font-medium leading-[18px] text-[#DC6803]">{t('promptMode.contextMissing', { ns: 'appDebug' })}</div>
      </div>
      <Button
        size="small"
        variant="secondary-accent"
        onClick={onHideContextMissingTip}
      >
        {t('operation.ok', { ns: 'common' })}
      </Button>
    </div>
  )
  return (
    <div className={`rounded-xl bg-gradient-to-r from-components-input-border-active-prompt-1 to-components-input-border-active-prompt-2 p-0.5 shadow-xs ${!isContextMissing ? '' : s.warningBorder}`}>
      <div className="rounded-xl bg-background-default">
        {isContextMissing
          ? contextMissing
          : (
              <div className={cn(s.boxHeader, 'flex h-11 items-center justify-between rounded-tl-xl rounded-tr-xl bg-background-default pb-1 pl-4 pr-3 pt-2 hover:shadow-xs')}>
                {isChatMode
                  ? (
                      <MessageTypeSelector value={type} onChange={onTypeChange} />
                    )
                  : (
                      <div className="flex items-center space-x-1">

                        <div className="text-sm font-semibold uppercase text-indigo-800">
                          {t('pageTitle.line1', { ns: 'appDebug' })}
                        </div>
                        <Tooltip
                          popupContent={(
                            <div className="w-[180px]">
                              {t('promptTip', { ns: 'appDebug' })}
                            </div>
                          )}
                        />
                      </div>
                    )}
                <div className={cn(s.optionWrap, 'items-center space-x-1')}>
                  {canDelete && (
                    <RiDeleteBinLine onClick={onDelete} className="h-6 w-6 cursor-pointer p-1 text-text-tertiary" />
                  )}
                  {!isCopied
                    ? (
                        <Copy
                          className="h-6 w-6 cursor-pointer p-1 text-text-tertiary"
                          onClick={() => {
                            copy(value)
                            setIsCopied(true)
                          }}
                        />
                      )
                    : (
                        <CopyCheck className="h-6 w-6 p-1 text-text-tertiary" />
                      )}
                </div>
              </div>
            )}

        <PromptEditorHeightResizeWrap
          className="min-h-[102px] overflow-y-auto px-4 text-sm text-text-secondary"
          height={editorHeight}
          minHeight={minHeight}
          onHeightChange={setEditorHeight}
          footer={(
            <div className="flex pb-2 pl-4">
              <div className="h-[18px] rounded-md bg-divider-regular px-1 text-xs leading-[18px] text-text-tertiary">{value.length}</div>
            </div>
          )}
          hideResize={noResize}
        >
          <PromptEditor
            className="min-h-[84px]"
            value={value}
            contextBlock={{
              show: true,
              selectable: !hasSetBlockStatus.context,
              datasets: dataSets.map(item => ({
                id: item.id,
                name: item.name,
                type: item.data_source_type,
              })),
              onAddContext: showSelectDataSet,
            }}
            variableBlock={{
              show: true,
              variables: modelConfig.configs.prompt_variables.filter(item => item.type !== 'api' && item.key && item.key.trim() && item.name && item.name.trim()).map(item => ({
                name: item.name,
                value: item.key,
              })),
            }}
            externalToolBlock={{
              externalTools: modelConfig.configs.prompt_variables.filter(item => item.type === 'api').map(item => ({
                name: item.name,
                variableName: item.key,
                icon: item.icon,
                icon_background: item.icon_background,
              })),
              onAddExternalTool: handleOpenExternalDataToolModal,
            }}
            historyBlock={{
              show: !isChatMode && isChatApp,
              selectable: !hasSetBlockStatus.history,
              history: {
                user: conversationHistoriesRole?.user_prefix,
                assistant: conversationHistoriesRole?.assistant_prefix,
              },
              onEditRole: showHistoryModal,
            }}
            queryBlock={{
              show: !isChatMode && isChatApp,
              selectable: !hasSetBlockStatus.query,
            }}
            onChange={handlePromptChange}
            onBlur={handleBlur}
          />
        </PromptEditorHeightResizeWrap>

      </div>

      {isShowConfirmAddVar && (
        <ConfirmAddVar
          varNameArr={newPromptVariables.map(v => v.name)}
          onConfirm={handleAutoAdd(true)}
          onCancel={handleAutoAdd(false)}
          onHide={hideConfirmAddVar}
        />
      )}
    </div>
  )
}
export default React.memo(AdvancedPromptInput)
