import React, { forwardRef, useCallback } from 'react'
import type { ReactNode } from 'react'
import { cva } from 'class-variance-authority'
import { cn } from '@/lib/utils'
import { SendButton } from '../send-button'
import { IconButton } from '../../basic/icon-button'
import { MoreLine } from '../../basic/icons-inline'
import { GenerationStatusBar } from '../generation-status-bar'
import { ChatInputTextarea } from './chat-input-textarea'
import { ChatInputFolderSelector } from './chat-input-folder-selector'
import { ChatInputModelSwitcher } from './chat-input-model-switcher'
import { useChatInputContext } from './context'

const chatInputContainerVariants = cva(
  [
    'flex flex-col w-full bg-bg-base border border-primary-border rounded-xl transition-all duration-200',
    /* 参考 Claude 输入框：2 级阴影默认，4 级 focus，使用本项目 1～4 级 shadow token */
    'shadow-[0_0.25rem_1.25rem_var(--color-shadow-secondary)]',
    'hover:shadow-[0_0.25rem_1.25rem_var(--color-shadow-secondary)]',
    'focus-within:shadow-[0_0.25rem_1.25rem_var(--color-shadow-quaternary)]',
    'hover:focus-within:shadow-[0_0.25rem_1.25rem_var(--color-shadow-quaternary)]',
  ].join(' '),
  {
    variants: { disabled: { true: 'opacity-50 cursor-not-allowed', false: '' } },
    defaultVariants: { disabled: false },
  }
)
// Box 使用 rounded-xl (= --radius-xl)

const attachmentRowStyles = 'flex flex-wrap items-center gap-2 px-3 pt-3 pb-2'
const contentStyles = 'flex flex-1 items-center min-h-6 p-3'
const footerStyles = 'flex shrink-0 items-center justify-between w-full self-stretch gap-2 p-3'

// ----- 框外 -----
// Above 高度 = 主题下 md 控件高度；宽度 = Box 宽度 - 2*圆角，居中；无水平 padding
export interface ChatInputAboveProps {
  className?: string
  style?: React.CSSProperties
  children?: ReactNode
}

export function ChatInputAbove({ className, style, children }: ChatInputAboveProps) {
  return (
    <div
      className={cn(
        'flex min-h-[var(--control-height-md)] h-[var(--control-height-md)] w-[calc(100%-2*var(--radius-xl))] mx-auto items-center overflow-hidden rounded-t-xl text-[length:var(--control-font-size-md)] leading-[var(--control-line-height-md)]',
        className
      )}
      style={style}
    >
      {children}
    </div>
  )
}
ChatInputAbove.displayName = 'ChatInputAbove'

// ----- 框容器 -----
export interface ChatInputBoxProps {
  className?: string
  children?: ReactNode
}

export function ChatInputBox({ className, children }: ChatInputBoxProps) {
  const ctx = useChatInputContext()
  return (
    <div
      className={chatInputContainerVariants({
        disabled: ctx.disabled,
        className: cn('relative', className),
      })}
    >
      {children}
    </div>
  )
}
ChatInputBox.displayName = 'ChatInputBox'

// ----- 框内·第一层 附件区 -----
export interface ChatInputAttachmentsProps {
  className?: string
  children?: ReactNode
}

export function ChatInputAttachments({ className, children }: ChatInputAttachmentsProps) {
  if (!children) return null
  return <div className={cn(attachmentRowStyles, className)}>{children}</div>
}
ChatInputAttachments.displayName = 'ChatInputAttachments'

// ----- 框内·第二层 输入区 -----
export interface ChatInputInputProps extends Omit<React.ComponentProps<typeof ChatInputTextarea>, 'value' | 'onChange' | 'onKeyDown'> {
  placeholder?: string
  maxRows?: number
}

export const ChatInputInput = forwardRef<HTMLTextAreaElement, ChatInputInputProps>(
  ({ placeholder, maxRows, ...props }, ref) => {
    const ctx = useChatInputContext()
    const setRef = useCallback(
      (node: HTMLTextAreaElement | null) => {
        ctx.setTextareaRef(node)
        if (typeof ref === 'function') ref(node)
        else if (ref) (ref as React.MutableRefObject<HTMLTextAreaElement | null>).current = node
      },
      [ctx, ref]
    )
    return (
      <div className={contentStyles}>
        <ChatInputTextarea
          ref={setRef}
          value={ctx.value}
          onChange={ctx.onChange}
          onKeyDown={ctx.handleKeyDown}
          placeholder={placeholder ?? ctx.placeholder}
          disabled={ctx.disabled}
          maxRows={maxRows ?? ctx.maxRows}
          {...props}
        />
      </div>
    )
  }
)
ChatInputInput.displayName = 'ChatInputInput'

// ----- 框内·第三层 操作区 -----
export interface ChatInputActionsProps {
  className?: string
  children?: ReactNode
}

export function ChatInputActions({ className, children }: ChatInputActionsProps) {
  return <div className={cn(footerStyles, className)}>{children}</div>
}
ChatInputActions.displayName = 'ChatInputActions'

export interface ChatInputActionsLeftProps {
  className?: string
  children?: ReactNode
}

export function ChatInputActionsLeft({ className, children }: ChatInputActionsLeftProps) {
  return <div className={cn('flex items-center gap-2', className)}>{children}</div>
}
ChatInputActionsLeft.displayName = 'ChatInputActionsLeft'

export interface ChatInputActionsRightProps {
  className?: string
  children?: ReactNode
}

export function ChatInputActionsRight({ className, children }: ChatInputActionsRightProps) {
  return <div className={cn('flex items-center gap-2', className)}>{children}</div>
}
ChatInputActionsRight.displayName = 'ChatInputActionsRight'

// ----- 固定·框内右上角放大按钮 -----
export interface ChatInputExpandButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
  children?: ReactNode
}

export function ChatInputExpandButton({ className, style, ...props }: ChatInputExpandButtonProps) {
  return (
    <button
      type="button"
      className={cn(
        'absolute top-2 right-2 z-10 flex h-8 w-8 items-center justify-center rounded-lg text-text-secondary hover:bg-fill-secondary hover:text-text focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-border disabled:opacity-50',
        className
      )}
      style={{ ...style }}
      {...props}
    />
  )
}
ChatInputExpandButton.displayName = 'ChatInputExpandButton'

// ----- 操作区子组件（从 Context 消费） -----
export function ChatInputFolderButton() {
  const ctx = useChatInputContext()
  if (!ctx.showFolderButton) return null
  return (
    <ChatInputFolderSelector
      disabled={ctx.disabled}
      folderButtonLabel={ctx.folderButtonLabel}
      folderPermission={ctx.folderPermission}
      onFolderButtonClick={ctx.onFolderButtonClick}
      onFolderClear={ctx.handleFolderClear}
      onFolderSelect={ctx.handleFolderSelect}
      hasFolderSelected={ctx.hasFolderSelected}
      dataStyle={ctx.dataStyle}
      dataTheme={ctx.dataTheme}
      folderIcon={ctx.folderIcon}
      folderOpenIcon={ctx.folderOpenIcon}
      historyIcon={ctx.historyIcon}
      subMenuArrowIcon={ctx.subMenuArrowIcon}
      folderFillIcon={ctx.folderFillIcon}
      closeIcon={ctx.closeIcon}
    />
  )
}
ChatInputFolderButton.displayName = 'ChatInputFolderButton'

export function ChatInputMoreButton() {
  const ctx = useChatInputContext()
  if (!ctx.showMoreButton) return null
  return (
    <IconButton
      variant="ghost"
      icon={ctx.addLargeIcon ?? <MoreLine className="h-5 w-5" />}
      onClick={ctx.onMoreButtonClick}
      disabled={ctx.disabled}
      aria-label="More actions"
    />
  )
}
ChatInputMoreButton.displayName = 'ChatInputMoreButton'

// 使用 chat 内共用的 SendButton，仅从 Context 注入 disabled/status/onClick|form
export function ChatInputSendButton() {
  const ctx = useChatInputContext()
  return (
    <SendButton
      disabled={!ctx.canSend || ctx.disabled}
      status={ctx.sendButtonStatus}
      {...(ctx.form ? { type: 'submit' as const, form: ctx.form } : { onClick: ctx.handleSend })}
    />
  )
}
ChatInputSendButton.displayName = 'ChatInputSendButton'

// 左侧操作区默认内容：有 footerLeftConfig 时渲染模式/模型切换，否则渲染 FolderButton + MoreButton
export function ChatInputFooterLeft() {
  const ctx = useChatInputContext()
  if (ctx.footerLeftConfig) {
    return (
      <ChatInputModelSwitcher
        config={ctx.footerLeftConfig}
        disabled={ctx.disabled}
        arrowDownIcon={ctx.arrowDownIcon}
        dataStyle={ctx.dataStyle}
        dataTheme={ctx.dataTheme}
      />
    )
  }
  return (
    <>
      <ChatInputFolderButton />
      <ChatInputMoreButton />
    </>
  )
}
ChatInputFooterLeft.displayName = 'ChatInputFooterLeft'

// ----- 默认布局（ChatInput 便捷导出使用） -----
export interface ChatInputDefaultLayoutProps {
  className?: string
  hasAbove?: boolean
  hasAttachments?: boolean
  hasFooter?: boolean
  aboveOverlap?: boolean
}

export const ChatInputDefaultLayout = forwardRef<HTMLTextAreaElement, ChatInputDefaultLayoutProps>(
  function ChatInputDefaultLayout(
    { className, hasAbove = false, hasAttachments = false, hasFooter = true, aboveOverlap = true },
    ref
  ) {
    const ctx = useChatInputContext()
    void aboveOverlap

    const renderAttachments = () => {
    if (!hasAttachments || ctx.attachments == null || ctx.attachments === false) return null
    const att = ctx.attachments
    if (typeof att === 'object' && !React.isValidElement(att) && ('files' in att || 'images' in att)) {
      return (
        <>
          {(att as { files?: ReactNode }).files && (
            <div className={attachmentRowStyles}>{(att as { files?: ReactNode }).files}</div>
          )}
          {(att as { images?: ReactNode }).images && (
            <div className={attachmentRowStyles}>{(att as { images?: ReactNode }).images}</div>
          )}
        </>
      )
    }
    return <div className={attachmentRowStyles}>{att as ReactNode}</div>
  }

  const renderFooterLeft = () => <ChatInputFooterLeft />

  const boxContent = (
    <ChatInputBox className={cn(!hasFooter && !hasAttachments && 'min-h-14')}>
      {renderAttachments()}
      <ChatInputInput ref={ref} />
      {/* 始终保留操作区右侧 SendButton：hasFooter 时显示完整 footer，否则仅显示右侧发送按钮（Minimal 模式） */}
      <ChatInputActions>
        {hasFooter ? (
          <>
            <ChatInputActionsLeft>{renderFooterLeft()}</ChatInputActionsLeft>
            <div className="flex-1 h-5" />
            <ChatInputActionsRight>
              <ChatInputSendButton />
            </ChatInputActionsRight>
          </>
        ) : (
          <>
            <div className="flex-1 h-5" />
            <ChatInputActionsRight>
              <ChatInputSendButton />
            </ChatInputActionsRight>
          </>
        )}
      </ChatInputActions>
    </ChatInputBox>
  )

  if (hasAbove && ctx.showGenerationStatus && ctx.generationStatus) {
    return (
      <div className={cn('flex flex-col w-full', className)}>
        <ChatInputAbove>
          <GenerationStatusBar
            status={typeof ctx.generationStatus?.content === 'string' ? ctx.generationStatus.content : undefined}
            icon={ctx.generationStatus?.icon}
            time={ctx.generationStatus?.time}
          >
            {ctx.generationStatus?.content}
          </GenerationStatusBar>
        </ChatInputAbove>
        {boxContent}
      </div>
    )
  }

  return <div className={className}>{boxContent}</div>
  }
)
ChatInputDefaultLayout.displayName = 'ChatInputDefaultLayout'
