import type {
  ChangeEvent,
  CSSProperties,
  DragEvent as ReactDragEvent,
  KeyboardEvent as ReactKeyboardEvent,
  PointerEvent as ReactPointerEvent,
  ReactNode,
  RefObject,
  UIEvent as ReactUIEvent
} from "react"
import type { ChatAttachment, ChatLaunchState, ProjectIntentSuggestion } from "@qjclaw/shared-types"
import type { ExpertGuideContent } from "../experts/ExpertsView"
import { ExpertEmptyState } from "../experts/ExpertsView"
import type { ExpertVisualKey } from "../shell/ExpertTree"
import { BindEntry } from "./BindEntry"
import { ChatComposer } from "./ChatComposer"
import { ChatWorkspace } from "./ChatWorkspace"
import { ConversationStatusNotice, HomeIntentSuggestionNotice } from "./ConversationNotices"
import { MessageList, type ExpertKey, type MessageListMessage } from "./MessageList"
import type { MessageTraceState } from "./useMessageTraces"

type ViewMode = "chat" | "experts" | "tasks" | "plugins" | "settings" | "knowledge"
type MessageReaction = "up" | "down"

interface HomeStarterPrompt {
  title: string
  description: string
  prompt: string
}

interface ConversationWorkspaceViewProps {
  viewMode: ViewMode
  workspaceRef: RefObject<HTMLDivElement | null>
  messageListRef: RefObject<HTMLDivElement | null>
  attachmentInputRef: RefObject<HTMLInputElement | null>
  skillMenuRef: RefObject<HTMLDivElement | null>
  panelActions: ReactNode
  selectedSkillBadge: string
  selectedSkillIsDefault: boolean
  homeLeadIcon: ReactNode
  activeExpertName: string
  activeExpertKey: ExpertKey
  activeExpertVisualKey: ExpertVisualKey
  activeExpertGuide: ExpertGuideContent
  expertWorkspaceLogo: ReactNode
  renderExpertIcon: (expertKey: ExpertVisualKey) => ReactNode
  showInlineStartupNotice: boolean
  chatLaunchState: ChatLaunchState
  startupCurtainStatus: string
  homeIntentSuggestion: ProjectIntentSuggestion | null
  homeIntentDecisionPending: boolean
  homeIntentLabels: {
    title: string
    prefix: string
    suffix: string
    continue: string
    switchAction: string
  }
  renderIntentIcon: (projectId: string) => ReactNode
  onContinueHomeIntent: () => void | Promise<unknown>
  onSwitchHomeIntent: () => void | Promise<unknown>
  showBindEntry: boolean
  bindEntry: {
    lobsterKeyDraft: string
    workspaceApiKeyConfigured: boolean
    saving: boolean
    bindingLabel: string
    onLobsterKeyChange: (value: string) => void
    onSave: () => void | Promise<void>
  }
  hasExpertProjects: boolean
  noExpertsLabel: string
  starterQuestionsHint: string
  homeEmptyTitle: string
  homePrompts: readonly HomeStarterPrompt[]
  onStarterPrompt: (prompt: string) => void
  messages: MessageListMessage[]
  showEmptyState: boolean
  messageTraces: Record<string, MessageTraceState>
  messageReactions: Record<string, MessageReaction | undefined>
  copiedToken: string
  sending: boolean
  messageLabels: {
    thinking: string
    hideTrace: string
    traceCollapsed: string
  }
  copyIcon: ReactNode
  copiedIcon: ReactNode
  deleteIcon: ReactNode
  regenerateIcon: ReactNode
  renderThumbIcon: (direction: MessageReaction) => ReactNode
  renderMarkdownContent: (
    content: string,
    options: {
      messageId: string
      copiedToken: string
      onCopy: (token: string, text: string) => void | Promise<void>
    }
  ) => ReactNode[]
  buildDouyinVideoStatusCard: (message: MessageListMessage, expertKey: ExpertKey) => {
    title: string
    meta?: string
    hint?: string
  } | null
  formatMessageTimestamp: (value: string) => string
  onMessageListScroll: (event: ReactUIEvent<HTMLDivElement>) => void
  onCopyText: (token: string, text: string) => void | Promise<void>
  onDeleteMessage: (messageId: string) => void
  onTraceExpandedChange: (messageId: string, expanded: boolean) => void
  onRegenerateAssistantMessage: (messageId: string) => void | Promise<void>
  onToggleMessageReaction: (messageId: string, reaction: MessageReaction) => void
  prompt: string
  isBound: boolean
  canSend: boolean
  isComposerDragOver: boolean
  isComposerResizeActive: boolean
  composerShellStyle: CSSProperties
  attachmentAccept: string
  attachments: ChatAttachment[]
  composerPlaceholder: string
  sendButtonLabel: string
  skillMenuTitle: string
  defaultChatLabel: string
  defaultSkillId: string
  selectedSkillId: string
  selectedSkillName: string
  skills: Array<{ id: string; name: string; description: string }>
  skillMenuOpen: boolean
  attachmentIcon: ReactNode
  submitIcon: ReactNode
  onSubmit: () => 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 ConversationWorkspaceView({
  viewMode,
  workspaceRef,
  messageListRef,
  attachmentInputRef,
  skillMenuRef,
  panelActions,
  selectedSkillBadge,
  selectedSkillIsDefault,
  homeLeadIcon,
  activeExpertName,
  activeExpertKey,
  activeExpertVisualKey,
  activeExpertGuide,
  expertWorkspaceLogo,
  renderExpertIcon,
  showInlineStartupNotice,
  chatLaunchState,
  startupCurtainStatus,
  homeIntentSuggestion,
  homeIntentDecisionPending,
  homeIntentLabels,
  renderIntentIcon,
  onContinueHomeIntent,
  onSwitchHomeIntent,
  showBindEntry,
  bindEntry,
  hasExpertProjects,
  noExpertsLabel,
  starterQuestionsHint,
  homeEmptyTitle,
  homePrompts,
  onStarterPrompt,
  messages,
  showEmptyState,
  messageTraces,
  messageReactions,
  copiedToken,
  sending,
  messageLabels,
  copyIcon,
  copiedIcon,
  deleteIcon,
  regenerateIcon,
  renderThumbIcon,
  renderMarkdownContent,
  buildDouyinVideoStatusCard,
  formatMessageTimestamp,
  onMessageListScroll,
  onCopyText,
  onDeleteMessage,
  onTraceExpandedChange,
  onRegenerateAssistantMessage,
  onToggleMessageReaction,
  prompt,
  isBound,
  canSend,
  isComposerDragOver,
  isComposerResizeActive,
  composerShellStyle,
  attachmentAccept,
  attachments,
  composerPlaceholder,
  sendButtonLabel,
  skillMenuTitle,
  defaultChatLabel,
  defaultSkillId,
  selectedSkillId,
  selectedSkillName,
  skills,
  skillMenuOpen,
  attachmentIcon,
  submitIcon,
  onSubmit,
  onPromptChange,
  onTextareaKeyDown,
  onAttachmentSelection,
  onOpenAttachmentPicker,
  onRemoveAttachment,
  onToggleSkillMenu,
  onClearSelectedSkill,
  onChooseSkill,
  onDragEnter,
  onDragOver,
  onDragLeave,
  onDrop,
  onResizePointerDown,
  onResizePointerMove,
  onResizePointerEnd
}: ConversationWorkspaceViewProps) {
  const homeMicrocopyStatus = selectedSkillIsDefault ? "默认工作区" : "已切换"

  const panelLead = viewMode === "chat" ? (
    <div className="home-microcopy" aria-label={`工作区，${selectedSkillBadge}`}>
      <span className="home-microcopy-icon-shell" aria-hidden="true">
        <span className="home-microcopy-icon">
          {homeLeadIcon}
        </span>
        <span className="home-microcopy-icon-beam" />
      </span>
      <span className="home-microcopy-body">
        <strong className="home-microcopy-title">{selectedSkillBadge}</strong>
      </span>
      <span className={"home-microcopy-status" + (selectedSkillIsDefault ? " brand" : "")}>
        {homeMicrocopyStatus}
      </span>
    </div>
  ) : (
    <div className="conversation-panel-kicker expert-hero-kicker">
      {expertWorkspaceLogo ?? (
        <span className={"expert-hero-icon expert-hero-icon-" + activeExpertVisualKey} aria-hidden="true">
          {renderExpertIcon(activeExpertVisualKey)}
        </span>
      )}
      <span className="expert-hero-copy">
        <strong>{activeExpertName}</strong>
      </span>
    </div>
  )

  const activeEmptyState = viewMode === "experts" ? (
    <ExpertEmptyState
      activeExpertName={activeExpertName}
      activeExpertKey={activeExpertKey}
      activeExpertGuide={activeExpertGuide}
      starterQuestionsHint={starterQuestionsHint}
      onStarterPrompt={onStarterPrompt}
    />
  ) : (
    <div className="empty-state home-empty-state">
      <div className="home-empty-copy">
        <strong className="home-empty-title">{homeEmptyTitle}</strong>
      </div>
      <div className="starter-prompt-list" aria-label="可选任务入口">
        {homePrompts.map((item) => (
          <button
            key={item.prompt}
            type="button"
            className="starter-prompt"
            title={item.prompt}
            aria-label={item.prompt}
            onClick={() => onStarterPrompt(item.prompt)}
          >
            <span className="starter-prompt-title">{item.title}</span>
            <span className="starter-prompt-desc">{item.description}</span>
          </button>
        ))}
      </div>
    </div>
  )

  const statusNotice = (
    <ConversationStatusNotice
      show={showInlineStartupNotice}
      chatLaunchState={chatLaunchState}
      status={startupCurtainStatus}
    />
  )

  const intentNotice = viewMode === "chat" ? (
    <HomeIntentSuggestionNotice
      suggestion={homeIntentSuggestion}
      decisionPending={homeIntentDecisionPending}
      labels={homeIntentLabels}
      renderIcon={renderIntentIcon}
      onContinue={onContinueHomeIntent}
      onSwitch={onSwitchHomeIntent}
    />
  ) : null

  const bodyContent = showBindEntry
    ? (
        <BindEntry
          lobsterKeyDraft={bindEntry.lobsterKeyDraft}
          workspaceApiKeyConfigured={bindEntry.workspaceApiKeyConfigured}
          saving={bindEntry.saving}
          bindingLabel={bindEntry.bindingLabel}
          onLobsterKeyChange={bindEntry.onLobsterKeyChange}
          onSave={bindEntry.onSave}
        />
      )
    : viewMode === "experts" && !hasExpertProjects
      ? <div className="empty-state">{noExpertsLabel}</div>
      : (
          <MessageList
            messages={messages}
            viewMode={viewMode}
            showBindEntry={showBindEntry}
            showEmptyState={showEmptyState}
            emptyState={activeEmptyState}
            messageListRef={messageListRef}
            messageTraces={messageTraces}
            messageReactions={messageReactions}
            copiedToken={copiedToken}
            sending={sending}
            activeExpertKey={activeExpertKey}
            labels={messageLabels}
            copyIcon={copyIcon}
            copiedIcon={copiedIcon}
            deleteIcon={deleteIcon}
            regenerateIcon={regenerateIcon}
            renderThumbIcon={renderThumbIcon}
            renderMarkdownContent={renderMarkdownContent}
            buildDouyinVideoStatusCard={buildDouyinVideoStatusCard}
            formatMessageTimestamp={formatMessageTimestamp}
            onScroll={onMessageListScroll}
            onCopyText={onCopyText}
            onDeleteMessage={onDeleteMessage}
            onTraceExpandedChange={onTraceExpandedChange}
            onRegenerateAssistantMessage={onRegenerateAssistantMessage}
            onToggleMessageReaction={onToggleMessageReaction}
          />
        )

  const composerContent = (
    <ChatComposer
      prompt={prompt}
      isBound={isBound}
      sending={sending}
      canSend={canSend}
      isDragOver={isComposerDragOver}
      isResizeActive={isComposerResizeActive}
      viewMode={viewMode}
      shellStyle={composerShellStyle}
      attachmentInputRef={attachmentInputRef}
      skillMenuRef={skillMenuRef}
      attachmentAccept={attachmentAccept}
      attachments={attachments}
      placeholder={composerPlaceholder}
      sendButtonLabel={sendButtonLabel}
      skillMenuTitle={skillMenuTitle}
      defaultChatLabel={defaultChatLabel}
      defaultSkillId={defaultSkillId}
      selectedSkillId={selectedSkillId}
      selectedSkillName={selectedSkillName}
      skills={skills}
      skillMenuOpen={skillMenuOpen}
      attachmentIcon={attachmentIcon}
      submitIcon={submitIcon}
      onSubmit={onSubmit}
      onPromptChange={onPromptChange}
      onTextareaKeyDown={onTextareaKeyDown}
      onAttachmentSelection={onAttachmentSelection}
      onOpenAttachmentPicker={onOpenAttachmentPicker}
      onRemoveAttachment={onRemoveAttachment}
      onToggleSkillMenu={onToggleSkillMenu}
      onClearSelectedSkill={onClearSelectedSkill}
      onChooseSkill={onChooseSkill}
      onDragEnter={onDragEnter}
      onDragOver={onDragOver}
      onDragLeave={onDragLeave}
      onDrop={onDrop}
      onResizePointerDown={onResizePointerDown}
      onResizePointerMove={onResizePointerMove}
      onResizePointerEnd={onResizePointerEnd}
    />
  )

  return (
    <ChatWorkspace
      panelLead={panelLead}
      panelActions={panelActions}
      workspaceRef={workspaceRef}
      statusNotice={statusNotice}
      intentNotice={intentNotice}
      bodyContent={bodyContent}
      composerContent={composerContent}
    />
  )
}
