import React, { useState, useCallback, useRef, type KeyboardEvent } from 'react'
import { ArrowUp, StopCircle, Paperclip, Wrench } from 'lucide-react'
import { cn } from '@/utils/cn'
import { Textarea } from '@/components/ui/textarea'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
import type { SendMessagePayload } from '../types'
import { Button } from '@/components/ui'
import { useNovaKit } from '../context/useNovaKit'
import { useFileUploader } from '../hooks/useFileUploader'
import type { UploadFile } from '../types'
import { FilePreviewList } from './FilePreviewList'
import { request } from '@/http/request'
import {
  McpStorePopover,
  SkillForm,
  type SkillFormState,
  MCPJsonEditor,
} from '../tools'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { toast } from 'sonner'
import { TaskStatus } from '../types'
import { getProjectId, getUserId } from '@/utils/getAuth'

interface InputToolsProps {
  showUpload?: boolean
  fileInputRef: React.RefObject<HTMLInputElement | null>
  accept?: string
  onFileSelect: (e: React.ChangeEvent<HTMLInputElement>) => void
  onOpenSkillManager: () => void
  onOpenMcpManager: () => void
}

const InputTools: React.FC<InputToolsProps> = ({
  showUpload,
  fileInputRef,
  accept,
  onFileSelect,
  onOpenSkillManager,
  onOpenMcpManager,
}) => {
  if (!showUpload) return null

  return (
    <TooltipProvider>
      <div className="flex items-center gap-2">
        {/* 上传文件 */}
        <Tooltip>
          <TooltipTrigger asChild>
            <button
              type="button"
              onClick={() => fileInputRef.current?.click()}
              className="inline-flex items-center justify-center rounded-full w-7 h-7 bg-gray-100 text-gray-900 transition-colors hover:bg-gray-200"
            >
              <Paperclip className="w-3.5 h-3.5" />
            </button>
          </TooltipTrigger>
          <TooltipContent>
            <p>上传文件</p>
          </TooltipContent>
        </Tooltip>

        <input
          type="file"
          multiple
          className="hidden"
          ref={fileInputRef}
          onChange={onFileSelect}
          accept={accept}
        />

        {/* 中间按钮：Popover，提供 Skill / MCP 选项 */}
        <Popover>
          <Tooltip>
            <TooltipTrigger asChild>
              <PopoverTrigger asChild>
                <button
                  type="button"
                  className="inline-flex items-center justify-center rounded-full w-7 h-7 bg-gray-100 text-gray-900 transition-colors hover:bg-gray-200"
                >
                  <Wrench className="w-3.5 h-3.5" />
                </button>
              </PopoverTrigger>
            </TooltipTrigger>
            <TooltipContent>
              添加工具
            </TooltipContent>
          </Tooltip>
          <PopoverContent
            align="start"
            className="w-40 p-1 bg-popover border border-border"
          >
            <button
              type="button"
              className="w-full cursor-pointer rounded-md px-3 py-3 text-left text-xs text-foreground transition-colors hover:bg-accent"
              onClick={onOpenSkillManager}
            >
              添加 Skill
            </button>
            <button
              type="button"
              className="mt-0.5 w-full cursor-pointer rounded-md px-3 py-3 text-left text-xs text-foreground transition-colors hover:bg-accent"
              onClick={onOpenMcpManager}
            >
              添加 MCP
            </button>
          </PopoverContent>
        </Popover>

        {/* MCP 市场入口 */}
        <McpStorePopover />
      </div>
    </TooltipProvider>
  )
}


export interface MessageInputProps {
  /** 占位符文本 */
  placeholder?: string
  /** 是否禁用 */
  disabled?: boolean
  /** 是否正在加载 */
  loading?: boolean
  /** 任务状态 */
  taskStatus?: TaskStatus
  /** 发送消息回调 */
  onSend?: (payload: SendMessagePayload) => void
  /** 终止消息回调 */
  onStop?: () => void
  /** 文件列表变化回调 */
  onFilesChange?: (files: UploadFile[]) => void
  /** 自定义类名 */
  className?: string
  /** 是否显示文件上传按钮 */
  showUpload?: boolean
}

/**
 * 消息输入框组件
 */
export function MessageInput({
  placeholder = '请输入消息...',
  taskStatus = TaskStatus.PENDING,
  onSend,
  className,
  showUpload = true,
}: MessageInputProps) {
  const { api: { stopChat }, loading, agentId } = useNovaKit()
  const [content, setContent] = useState('')
  const [files, setFiles] = useState<UploadFile[]>([])
  const textareaRef = useRef<HTMLTextAreaElement>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [skillDialogOpen, setSkillDialogOpen] = useState(false)
  const [mcpDialogOpen, setMcpDialogOpen] = useState(false)
  const [mcpJson, setMcpJson] = useState('')

  const handleUploadEnd = useCallback((file: UploadFile) => {
    setFiles(prev => prev.map(f => f.uid === file.uid ? file : f))
  }, [])

  const handleUploadStart = useCallback((file: UploadFile) => {
    setFiles(prev => [...prev, file])
  }, [])

  const handleFileUpdate = useCallback((file: UploadFile) => {
    setFiles(prev => prev.map(f => f.uid === file.uid ? file : f))
  }, [])

  const { uploadFile, accept } = useFileUploader({
    onUploadStart: handleUploadStart,
    onFileUpdate: handleFileUpdate,
    onUploadEnd: handleUploadEnd,
  })

  // Filter valid files and check loading status
  const uploading = files.some(f => f.uploadStatus === 'uploading' || f.uploadStatus === 'pending')
  const contentEmpty = !content.trim() && files.length === 0
  const showStopButton =
    (loading || taskStatus === TaskStatus.IN_PROGRESS) &&
    taskStatus !== TaskStatus.PAUSED

  const handleFileSelect = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) {
      const selectedFiles = Array.from(e.target.files)
      for (const file of selectedFiles) {
        await uploadFile(file)
      }
      // Reset input
      if (fileInputRef.current) fileInputRef.current.value = ''
    }
  }, [uploadFile])

  const removeFile = useCallback((uid: string) => {
    setFiles(prev => prev.filter(f => f.uid !== uid))
  }, [])

  // 发送消息
  const handleSend = useCallback(() => {
    if (contentEmpty) return
    
    // Check if any files are still uploading
    if (uploading) {
      console.warn('请等待文件上传完成')
      return
    }

    // Filter out failed uploads
    const validFiles = files.filter(f => f.uploadStatus === 'success')
    const fileIds = validFiles.map(f => f.upload_file_id).filter(Boolean) as string[]

    const payload: SendMessagePayload = {
      content: content.trim(),
      upload_file_ids: fileIds.length > 0 ? fileIds : undefined
    }

    // Ensure we are sending the file IDs as requested
    console.log('Sending message payload:', payload)

    onSend?.(payload)
    setContent('')
    setFiles([])

    // 清空已上传的文件
  }, [content, contentEmpty, onSend, files, uploading])

  // 处理键盘事件
  const handleKeyDown = useCallback(
    (e: KeyboardEvent<HTMLTextAreaElement>) => {
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault()
        handleSend()
      }
    },
    [handleSend]
  )

  // 自动调整高度
  const handleInput = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const textarea = e.target
    setContent(textarea.value)

    // 自动调整高度
    textarea.style.height = 'auto'
    textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`
  }, [])

  return (
    <>
    <div className={cn('w-full', className)}>
      <div className="max-w-2xl mx-auto w-full">
        <div className="relative group/input">
          {/* 渐变光晕背景层 */}

          {/* 主输入容器：上方 textarea，下方工具栏 / 发送按钮 */}
          <div className="relative flex w-full flex-col rounded-2xl border border-gray-200 bg-white px-4 pt-3 pb-3">
            {/* 文件预览区域 */}
            <FilePreviewList
              files={files}
              onRemove={removeFile}
              disabled={loading}
            />

            {/* 文本输入区域（顶部整行） */}
            <div className="flex-1 relative">
              <Textarea
                ref={textareaRef}
                value={content}
                onChange={handleInput}
                onKeyDown={handleKeyDown}
                placeholder={placeholder}
                rows={1}
                className={cn(
                  'w-full resize-none border-0 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0',
                  'bg-transparent min-h-[40px] max-h-[160px] px-0',
                  'placeholder:text-muted-foreground/70',
                  'text-foreground text-sm leading-relaxed',
                  'overflow-y-auto transition-all duration-200',
                  '[&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar-thumb]:bg-muted-foreground/40 [&::-webkit-scrollbar-thumb]:rounded-full'
                )}
              />
            </div>

            {/* 底部工具栏 + 发送按钮（参考截图布局） */}
            <div className="mt-2 pt-2 flex items-center justify-between text-[11px] text-muted-foreground">
              {/* 左侧：Agent Input + 工具区 */}
              <div className="flex items-center gap-3 text-muted-foreground">
                <InputTools
                  showUpload={showUpload}
                  fileInputRef={fileInputRef}
                  accept={accept}
                  onFileSelect={handleFileSelect}
                  onOpenSkillManager={() => {
                    setSkillDialogOpen(true)
                  }}
                  onOpenMcpManager={() => {
                    setMcpDialogOpen(true)
                  }}
                />
              </div>

              {/* 右侧：终止 + 发送按钮（发送为黑色圆形按钮） */}
              <div className="flex items-center gap-2 shrink-0">
                {showStopButton && (
                  <Button
                    type="button"
                    size="sm"
                    variant="outline"
                    onClick={() => {
                      void stopChat().catch(() => {})
                    }}
                    title="终止"
                    className={cn(
                      'h-8 rounded-full px-2.5 pr-3 text-[11px] font-medium transition-all duration-200',
                      'border border-rose-200/80 bg-rose-50/90 text-rose-600 hover:bg-rose-100 hover:text-rose-700 hover:border-rose-300',
                      'dark:border-rose-500/40 dark:bg-rose-500/10 dark:text-rose-100 dark:hover:bg-rose-500/20 dark:hover:border-rose-400'
                    )}
                  >
                    <StopCircle className="w-3.5 h-3.5" />
                  </Button>
                )}

                <button
                  type="button"
                  onClick={handleSend}
                  disabled={contentEmpty}
                  title="发送"
                  className={cn(
                    'flex h-8 w-8 items-center justify-center rounded-full bg-gray-900 text-white transition-all',
                    'hover:scale-105 active:scale-95 hover:bg-black',
                    contentEmpty && 'opacity-30 cursor-not-allowed hover:scale-100 hover:bg-gray-900'
                  )}
                >
                  <ArrowUp className="w-4 h-4" strokeWidth={2.3} />
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    {/* Skill 管理弹窗 */}
    <Dialog open={skillDialogOpen} onOpenChange={setSkillDialogOpen}>
      <DialogContent className="max-w-2xl border-border bg-card">
        <DialogHeader>
          <DialogTitle>添加 Skill</DialogTitle>
        </DialogHeader>
        <div className="mt-4 overflow-hidden rounded-lg">
          <SkillForm
            teamId={agentId!}
            onBack={() => setSkillDialogOpen(false)}
            onSave={async (values: SkillFormState) => {
              if (!agentId) {
                toast.error('缺少 agentId，无法创建 Skill')
                return
              }

              if (!values.file?.file) {
                toast.error('请先上传 Skill zip 文件')
                return
              }

              try {
                const formData = new FormData()
                formData.append('name', values.name)
                formData.append('agent_id', agentId)
                formData.append('file', values.file.file)

                /** 存在projectId的时候上传external_app_id */
                if (getProjectId()) {
                  formData.append('external_app_id', getProjectId()!)
                }

                const userId = await getUserId()
                /** 存在userId的时候上传external_user_id */
                if (userId) {
                  formData.append('external_user_id', userId)
                }

                if (values.description) {
                  formData.append('description', values.description)
                }

                await request.post('/plugins/skill/upload', formData, {
                  headers: {
                    'Content-Type': 'multipart/form-data',
                  },
                })
                toast.success('Skill 添加成功')
                setSkillDialogOpen(false)
              } catch (error) {
                console.error('创建 Skill 失败:', error)
                toast.error('创建 Skill 失败')
              }
            }}
          />
        </div>
      </DialogContent>
    </Dialog>
    
    {/* MCP 管理弹窗 */}
    <Dialog open={mcpDialogOpen} onOpenChange={setMcpDialogOpen}>
      <DialogContent className="max-w-3xl">
        <DialogHeader>
          <DialogTitle>添加 MCP</DialogTitle>
        </DialogHeader>
        <div className="mt-4">
          <MCPJsonEditor
            value={mcpJson}
            onChange={setMcpJson}
            onSave={async (parsedConfig: Record<string, unknown>) => {
              console.log('保存 MCP', { agentId, parsedConfig })
              if (!agentId) {
                toast.error('缺少 agentId，无法创建 MCP')
                return
              }

              try {
                await request.post(`/team/${agentId}/plugins`, {
                  name: parsedConfig.name,
                  code: parsedConfig.code,
                  plugin_type: 'MCP',
                  source: 'CLOUD',
                  config: parsedConfig,
                })
                toast.success('MCP 添加成功')
                setMcpJson('')
                setMcpDialogOpen(false)
              } catch (error) {
                console.error('创建 MCP 失败:', error)
                toast.error('创建 MCP 失败')
              }
            }}
          />
        </div>
      </DialogContent>
    </Dialog>
    </>
  )
}

export default React.memo(MessageInput)
