import type { SuggestedQuestionsAfterAnswer } from '@/app/components/base/features/types'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import type {
  CompletionParams,
  Model,
  ModelModeType,
} from '@/types/app'
import { Button } from '@langgenius/dify-ui/button'
import { cn } from '@langgenius/dify-ui/cn'
import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
import { FieldItem, FieldRoot } from '@langgenius/dify-ui/field'
import { FieldsetLegend, FieldsetRoot } from '@langgenius/dify-ui/fieldset'
import { RadioControl, RadioRoot } from '@langgenius/dify-ui/radio'
import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { Textarea } from '@langgenius/dify-ui/textarea'
import { produce } from 'immer'
import { useCallback, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
import { ModelModeType as ModelModeTypeEnum } from '@/types/app'

type FollowUpSettingModalProps = {
  data: SuggestedQuestionsAfterAnswer
  onSave: (newState: SuggestedQuestionsAfterAnswer) => void
  onCancel: () => void
}

const DEFAULT_COMPLETION_PARAMS: CompletionParams = {
  temperature: 0.7,
  max_tokens: 0,
  top_p: 0,
  echo: false,
  stop: [],
  presence_penalty: 0,
  frequency_penalty: 0,
}

const DEFAULT_FOLLOW_UP_PROMPT = `Please predict the three most likely follow-up questions a user would ask, keep each question under 20 characters, use the same language as the assistant's latest response, and output a JSON array like ["question1", "question2", "question3"].`
const CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH = 1000

const getInitialModel = (model?: Model): Model => ({
  provider: model?.provider || '',
  name: model?.name || '',
  mode: model?.mode || ModelModeTypeEnum.chat,
  completion_params: {
    ...DEFAULT_COMPLETION_PARAMS,
    ...(model?.completion_params || {}),
  },
})

const PROMPT_MODE = {
  default: 'default',
  custom: 'custom',
} as const

type PromptMode = typeof PROMPT_MODE[keyof typeof PROMPT_MODE]

const FollowUpSettingModal = ({
  data,
  onSave,
  onCancel,
}: FollowUpSettingModalProps) => {
  const { t } = useTranslation()
  const [model, setModel] = useState<Model>(() => getInitialModel(data.model))
  const [prompt, setPrompt] = useState(data.prompt || '')
  const [promptMode, setPromptMode] = useState<PromptMode>(
    data.prompt ? PROMPT_MODE.custom : PROMPT_MODE.default,
  )
  const { defaultModel } = useModelListAndDefaultModelAndCurrentProviderAndModel(ModelTypeEnum.textGeneration)
  const selectedModel = useMemo<Model>(() => {
    if (model.provider && model.name)
      return model

    if (!defaultModel)
      return model

    return {
      ...model,
      provider: defaultModel.provider.provider,
      name: defaultModel.model,
    }
  }, [defaultModel, model])

  const handleModelChange = useCallback((newValue: { modelId: string, provider: string, mode?: string, features?: string[] }) => {
    setModel(prev => ({
      ...prev,
      provider: newValue.provider,
      name: newValue.modelId,
      mode: (newValue.mode as ModelModeType) || prev.mode || ModelModeTypeEnum.chat,
    }))
  }, [])

  const handleCompletionParamsChange = useCallback((newParams: FormValue) => {
    setModel({
      ...selectedModel,
      completion_params: {
        ...DEFAULT_COMPLETION_PARAMS,
        ...(newParams as Partial<CompletionParams>),
      },
    })
  }, [selectedModel])

  const handleSave = useCallback(() => {
    const trimmedPrompt = prompt.trim()
    const nextFollowUpState = produce(data, (draft) => {
      if (selectedModel.provider && selectedModel.name)
        draft.model = selectedModel
      else
        draft.model = undefined

      draft.prompt = promptMode === PROMPT_MODE.custom
        ? (trimmedPrompt || undefined)
        : undefined
    })
    onSave(nextFollowUpState)
  }, [data, onSave, prompt, promptMode, selectedModel])

  const isCustomPromptInvalid = promptMode === PROMPT_MODE.custom && !prompt.trim()

  return (
    <Dialog
      open
      onOpenChange={(open) => {
        if (!open)
          onCancel()
      }}
    >
      <DialogContent className="w-[640px]! max-w-none! p-8! pb-6!">
        <DialogCloseButton className="top-8 right-8" />
        <DialogTitle className="pr-8 text-xl font-semibold text-text-primary">
          {t('feature.suggestedQuestionsAfterAnswer.modal.title', { ns: 'appDebug' })}
        </DialogTitle>
        <div className="mt-6 space-y-4">
          <div>
            <div className="mb-1.5 system-sm-semibold-uppercase text-text-secondary">
              {t('feature.suggestedQuestionsAfterAnswer.modal.modelLabel', { ns: 'appDebug' })}
            </div>
            <ModelParameterModal
              popupClassName="w-[520px]!"
              isAdvancedMode
              provider={selectedModel.provider}
              completionParams={selectedModel.completion_params}
              modelId={selectedModel.name}
              setModel={handleModelChange}
              onCompletionParamsChange={handleCompletionParamsChange}
              hideDebugWithMultipleModel
            />
          </div>
          <FieldRoot name="follow_up_prompt_mode" className="contents">
            <FieldsetRoot
              render={(
                <RadioGroup<PromptMode>
                  className="flex-col items-stretch gap-3"
                  value={promptMode}
                  onValueChange={setPromptMode}
                />
              )}
            >
              <FieldsetLegend className="mb-1.5 py-0 system-sm-semibold-uppercase text-text-secondary">
                {t('feature.suggestedQuestionsAfterAnswer.modal.promptLabel', { ns: 'appDebug' })}
              </FieldsetLegend>
              <FieldItem>
                <RadioRoot
                  value={PROMPT_MODE.default}
                  variant="unstyled"
                  nativeButton
                  render={<button type="button" />}
                  className={cn(
                    'w-full rounded-xl border p-4 text-left transition-colors',
                    promptMode === PROMPT_MODE.default
                      ? 'border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg'
                      : 'border-components-option-card-option-border bg-components-option-card-option-bg hover:bg-state-base-hover',
                  )}
                >
                  <div className="flex items-start justify-between gap-3">
                    <div>
                      <div className="system-sm-semibold text-text-primary">
                        {t('feature.suggestedQuestionsAfterAnswer.modal.defaultPromptOption', { ns: 'appDebug' })}
                      </div>
                      <div className="mt-1 system-xs-regular text-text-tertiary">
                        {t('feature.suggestedQuestionsAfterAnswer.modal.defaultPromptOptionDescription', { ns: 'appDebug' })}
                      </div>
                    </div>
                    <RadioControl aria-hidden="true" />
                  </div>
                  {promptMode === PROMPT_MODE.default && (
                    <div className="mt-3 rounded-lg border border-components-input-border-active bg-components-input-bg-normal px-3 py-2">
                      <div className="system-sm-regular wrap-break-word whitespace-pre-wrap text-text-secondary">
                        {DEFAULT_FOLLOW_UP_PROMPT}
                      </div>
                    </div>
                  )}
                </RadioRoot>
              </FieldItem>
              <FieldItem>
                <RadioRoot
                  value={PROMPT_MODE.custom}
                  variant="unstyled"
                  nativeButton
                  render={<button type="button" />}
                  className={cn(
                    'w-full rounded-xl border p-4 text-left transition-colors',
                    promptMode === PROMPT_MODE.custom
                      ? 'border-components-option-card-option-selected-border bg-components-option-card-option-selected-bg'
                      : 'border-components-option-card-option-border bg-components-option-card-option-bg hover:bg-state-base-hover',
                  )}
                >
                  <div className="flex items-start justify-between gap-3">
                    <div>
                      <div className="system-sm-semibold text-text-primary">
                        {t('feature.suggestedQuestionsAfterAnswer.modal.customPromptOption', { ns: 'appDebug' })}
                      </div>
                      <div className="mt-1 system-xs-regular text-text-tertiary">
                        {t('feature.suggestedQuestionsAfterAnswer.modal.customPromptOptionDescription', { ns: 'appDebug' })}
                      </div>
                    </div>
                    <RadioControl aria-hidden="true" />
                  </div>
                  {promptMode === PROMPT_MODE.custom && (
                    <Textarea
                      aria-label={t('feature.suggestedQuestionsAfterAnswer.modal.customPromptOption', { ns: 'appDebug' })}
                      className="mt-3 min-h-32 resize-y border-components-input-border-active bg-components-input-bg-normal"
                      value={prompt}
                      onValueChange={value => setPrompt(value)}
                      maxLength={CUSTOM_FOLLOW_UP_PROMPT_MAX_LENGTH}
                      placeholder={t('feature.suggestedQuestionsAfterAnswer.modal.promptPlaceholder', { ns: 'appDebug' }) || ''}
                    />
                  )}
                </RadioRoot>
              </FieldItem>
            </FieldsetRoot>
          </FieldRoot>
        </div>
        <div className="mt-6 flex items-center justify-end gap-2">
          <Button onClick={onCancel}>
            {t('operation.cancel', { ns: 'common' })}
          </Button>
          <Button
            variant="primary"
            disabled={isCustomPromptInvalid}
            onClick={handleSave}
          >
            {t('operation.save', { ns: 'common' })}
          </Button>
        </div>
      </DialogContent>
    </Dialog>
  )
}

export default FollowUpSettingModal
