import type {
  ChangeEvent,
  CSSProperties,
  DragEvent as ReactDragEvent,
  KeyboardEvent as ReactKeyboardEvent,
  PointerEvent as ReactPointerEvent,
  ReactNode,
  RefObject
} from "react"
import type { ChatAttachment } from "@qjclaw/shared-types"

interface ComposerSkill {
  id: string
  name: string
  description: string
}

interface ChatComposerProps {
  prompt: string
  isBound: boolean
  isChannelSession: boolean
  sending: boolean
  canSend: boolean
  isDragOver: boolean
  isResizeActive: boolean
  viewMode: "chat" | "experts" | "tasks" | "automation" | "plugins" | "settings" | "knowledge"
  shellStyle: CSSProperties
  attachmentInputRef: RefObject<HTMLInputElement | null>
  skillMenuRef: RefObject<HTMLDivElement | null>
  attachmentAccept: string
  attachments: ChatAttachment[]
  placeholder: string
  sendButtonLabel: string
  skillMenuTitle: string
  defaultChatLabel: string
  defaultSkillId: string
  selectedSkillId: string
  selectedSkillName: string
  skills: ComposerSkill[]
  skillMenuOpen: boolean
  attachmentIcon: ReactNode
  submitIcon: ReactNode
  onSubmit: () => void | Promise<void>
  onCancel: () => void | Promise<void>
  onPromptChange: (value: string) => void
  onTextareaKeyDown: (event: ReactKeyboardEvent<HTMLTextAreaElement>) => void | Promise<void>
  onAttachmentSelection: (event: ChangeEvent<HTMLInputElement>) => void
  onOpenAttachmentPicker: () => void
  onRemoveAttachment: (localPath: string) => void
  onToggleSkillMenu: () => void
  onClearSelectedSkill: () => void
  onChooseSkill: (skillId: string) => void
  onDragEnter: (event: ReactDragEvent<HTMLFormElement>) => void
  onDragOver: (event: ReactDragEvent<HTMLFormElement>) => void
  onDragLeave: (event: ReactDragEvent<HTMLFormElement>) => void
  onDrop: (event: ReactDragEvent<HTMLFormElement>) => void
  onResizePointerDown: (event: ReactPointerEvent<HTMLDivElement>) => void
  onResizePointerMove: (event: ReactPointerEvent<HTMLDivElement>) => void
  onResizePointerEnd: (event: ReactPointerEvent<HTMLDivElement>) => void
}

export function ChatComposer({
  prompt,
  isBound,
  isChannelSession,
  sending,
  canSend,
  isDragOver,
  isResizeActive,
  viewMode,
  shellStyle,
  attachmentInputRef,
  attachmentAccept,
  attachments,
  placeholder,
  sendButtonLabel,
  attachmentIcon,
  submitIcon,
  onSubmit,
  onCancel,
  onPromptChange,
  onTextareaKeyDown,
  onAttachmentSelection,
  onOpenAttachmentPicker,
  onRemoveAttachment,
  onDragEnter,
  onDragOver,
  onDragLeave,
  onDrop,
  onResizePointerDown,
  onResizePointerMove,
  onResizePointerEnd
}: ChatComposerProps) {
  return (
    <form
      className={
        "composer-shell"
        + (isDragOver ? " dragging" : "")
        + (isResizeActive ? " resizing" : "")
        + (viewMode === "chat" ? " composer-shell-home" : "")
        + (viewMode === "experts" ? " composer-shell-expert" : "")
      }
      style={shellStyle}
      onSubmit={(event) => {
        event.preventDefault()
        void onSubmit()
      }}
      onDragEnter={onDragEnter}
      onDragOver={onDragOver}
      onDragLeave={onDragLeave}
      onDrop={onDrop}
    >
      <input
        ref={attachmentInputRef}
        className="composer-attachment-input"
        type="file"
        accept={attachmentAccept}
        multiple
        tabIndex={-1}
        onChange={onAttachmentSelection}
      />
      {isDragOver ? <div className="composer-drop-indicator">释放以上传附件</div> : null}
      <div
        className="composer-resize-handle"
        role="separator"
        aria-orientation="horizontal"
        aria-label={"\u8c03\u6574\u8f93\u5165\u6846\u9ad8\u5ea6"}
        title={"\u8c03\u6574\u8f93\u5165\u6846\u9ad8\u5ea6"}
        onPointerDown={onResizePointerDown}
        onPointerMove={onResizePointerMove}
        onPointerUp={onResizePointerEnd}
        onPointerCancel={onResizePointerEnd}
      >
        <span aria-hidden="true" />
      </div>
      <div className="composer-surface">
        <label className="composer-field">
          <textarea
            value={prompt}
            disabled={!isBound || isChannelSession}
            onChange={(event) => onPromptChange(event.target.value)}
            onKeyDown={(event) => void onTextareaKeyDown(event)}
            placeholder={isChannelSession ? "飞书会话请在飞书中回复" : placeholder}
            className={"composer-textarea" + (isChannelSession ? " readonly" : "")}
          />
        </label>
        {attachments.length ? (
          <div className="composer-attachment-strip">
            {attachments.map((attachment) => (
              <span key={attachment.localPath} className="composer-attachment-chip">
                <span className="composer-attachment-chip-label">{attachment.name}</span>
                <button type="button" className="composer-attachment-remove" onClick={() => onRemoveAttachment(attachment.localPath)} aria-label={`移除附件 ${attachment.name}`}>
                  x
                </button>
              </span>
            ))}
          </div>
        ) : null}
        <div className="composer-footer">
          <div className="composer-left-tools">
            <button type="button" className="attachment-trigger icon-only" disabled={!isBound || isChannelSession || sending} onClick={onOpenAttachmentPicker} aria-label="上传附件" title="上传附件">
              {attachmentIcon}
            </button>
          </div>
          <button
            type={sending ? "button" : "submit"}
            className={"composer-submit" + (sending ? " is-busy" : "")}
            disabled={sending ? false : !canSend}
            onClick={sending ? onCancel : undefined}
            aria-label={sendButtonLabel}
            title={sendButtonLabel}
          >
            {submitIcon}
            <span className="visually-hidden">{sendButtonLabel}</span>
          </button>
        </div>
        <p className="composer-hint">{isChannelSession ? "飞书会话仅支持查看消息，回复请在飞书中操作" : "按 Enter 发送，Shift + Enter 换行"}</p>
      </div>
    </form>
  )
}
