/** Session JSX 렌더 트리 — index.tsx에서 분리 */

import { For, Match, Show, Switch, createSignal } from "solid-js"
import type { ScrollBoxRenderable } from "@opentui/core"
import { RGBA } from "@opentui/core"
import { SplitBorder } from "@tui/component/border"
import { Prompt } from "@tui/component/prompt"
import type { PromptRef } from "@tui/component/prompt"
import type { AssistantMessage, UserMessage, Provider } from "@saeeol/sdk/v2"
import { Sidebar } from "./sidebar"
import { SubagentFooter } from "./subagent-footer.tsx"
import { PermissionPrompt } from "./permission"
import { QuestionPrompt } from "./question"
import { SuggestPrompt } from "@/saeeol/suggestion/tui/prompt"
import { NetworkPrompt } from "./network"
import { SessionIndexing } from "@/saeeol/components/session-indexing"
import { TuiPluginRuntime } from "@/cli/cmd/tui/plugin/runtime"
import { Toast } from "../../ui/toast"
import { DialogMessage } from "./dialog-message"
import { DialogConfirm } from "@tui/ui/dialog-confirm"
import { useCommandDialog } from "@tui/component/dialog-command"
import { useDialog } from "../../ui/dialog"
import { useKeybind } from "@tui/context/keybind"
import { useRenderer } from "@opentui/solid"
import { useTheme } from "@tui/context/theme"
import { usePromptRef } from "../../context/prompt"
import { context } from "./context"
import { UserMessage as UserMessageComponent } from "./messages/user-message"
import { AssistantMessage as AssistantMessageComponent } from "./messages/assistant-message"
import type { useSync } from "@tui/context/sync"
import type { useTuiConfig } from "../../context/tui-config"

export interface LayoutDeps {
  sessionID: string
  session: () => any
  messages: () => any[]
  pending: () => string | undefined
  lastAssistant: () => any
  revert: () => { messageID: string; reverted: any[]; diff: string; diffFiles: any[] } | undefined
  permissions: () => any[]
  question: () => any
  blockingSuggestion: () => any
  network: () => any[]
  networkVisible: () => boolean
  visible: () => boolean
  disabled: () => boolean
  sidebarVisible: () => boolean
  wide: () => boolean
  contentWidth: () => number
  conceal: () => boolean
  showThinking: () => boolean
  showTimestamps: () => boolean
  showDetails: () => boolean
  showGenericToolOutput: () => boolean
  diffWrapMode: () => "word" | "none"
  showScrollbar: () => boolean
  scrollAcceleration: () => number
  providers: () => ReadonlyMap<string, Provider>
  scrollRef: (r: ScrollBoxRenderable) => void
  promptBind: (r: PromptRef | undefined) => void
  toBottom: () => void
  setSidebar: (fn: (prev: string) => string) => void
  setSidebarOpen: (v: boolean) => void
  sync: ReturnType<typeof useSync>
  tuiConfig: ReturnType<typeof useTuiConfig>
}

export function SessionLayout(props: { deps: LayoutDeps }) {
  const d = props.deps
  const { theme } = useTheme()
  const dialog = useDialog()
  const renderer = useRenderer()
  const keybind = useKeybind()
  const promptRef = usePromptRef()

  return (
    <context.Provider
      value={{
        get width() { return d.contentWidth() },
        sessionID: d.sessionID,
        conceal: d.conceal, showThinking: d.showThinking, showTimestamps: d.showTimestamps,
        showDetails: d.showDetails, showGenericToolOutput: d.showGenericToolOutput,
        diffWrapMode: d.diffWrapMode, providers: d.providers, sync: d.sync, tui: d.tuiConfig,
      }}
    >
      <box flexDirection="row">
        <box flexGrow={1} paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1}>
          <Show when={d.session()}>
            <scrollbox
              ref={d.scrollRef}
              viewportOptions={{ paddingRight: d.showScrollbar() ? 1 : 0 }}
              verticalScrollbarOptions={{
                paddingLeft: 1,
                visible: d.showScrollbar(),
                trackOptions: { backgroundColor: theme.backgroundElement, foregroundColor: theme.border },
              }}
              stickyScroll={true}
              stickyStart="bottom"
              flexGrow={1}
              scrollAcceleration={d.scrollAcceleration() as any}
            >
              <box height={1} />
              <Show when={d.session()?.parentID && d.messages().length === 0}>
                <box paddingLeft={3}>
                  <text fg={theme.textMuted}>↳ Initializing...</text>
                </box>
              </Show>
              <For each={d.messages()}>
                {(message: any, index: () => number) => (
                  <Switch>
                    <Match when={message.id === d.revert()?.messageID}>
                      {(function () {
                        const cmd = useCommandDialog()
                        const [hover, setHover] = createSignal(false)
                        const dlg = useDialog()
                        const handleUnrevert = async () => {
                          const confirmed = await DialogConfirm.show(dlg, "Confirm Redo", "Are you sure you want to restore the reverted messages?")
                          if (confirmed) cmd.trigger("session.redo")
                        }
                        return (
                          <box onMouseOver={() => setHover(true)} onMouseOut={() => setHover(false)} onMouseUp={handleUnrevert} marginTop={1} flexShrink={0} border={["left"]} customBorderChars={SplitBorder.customBorderChars} borderColor={theme.backgroundPanel}>
                            <box paddingTop={1} paddingBottom={1} paddingLeft={2} backgroundColor={hover() ? theme.backgroundElement : theme.backgroundPanel}>
                              <text fg={theme.textMuted}>{d.revert()!.reverted.length} message reverted</text>
                              <text fg={theme.textMuted}>
                                <span style={{ fg: theme.text }}>{keybind.print("messages_redo")}</span> or /redo to restore
                              </text>
                              <Show when={d.revert()!.diffFiles?.length}>
                                <box marginTop={1}>
                                  <For each={d.revert()!.diffFiles}>
                                    {(file: any) => (
                                      <text fg={theme.text}>
                                        {file.filename}
                                        <Show when={file.additions > 0}><span style={{ fg: theme.diffAdded }}> +{file.additions}</span></Show>
                                        <Show when={file.deletions > 0}><span style={{ fg: theme.diffRemoved }}> -{file.deletions}</span></Show>
                                      </text>
                                    )}
                                  </For>
                                </box>
                              </Show>
                            </box>
                          </box>
                        )
                      })()}
                    </Match>
                    <Match when={d.revert()?.messageID && message.id >= d.revert()!.messageID}>
                      <></>
                    </Match>
                    <Match when={message.role === "user"}>
                      <UserMessageComponent
                        index={index()}
                        onMouseUp={() => {
                          if (renderer.getSelection()?.getSelectedText()) return
                          dialog.replace(() => <DialogMessage messageID={message.id} sessionID={d.sessionID} setPrompt={(pi: any) => promptRef.current?.set(pi)} />)
                        }}
                        message={message as UserMessage}
                        parts={d.sync.data.part[message.id] ?? []}
                        pending={d.pending()}
                      />
                    </Match>
                    <Match when={message.role === "assistant"}>
                      <AssistantMessageComponent
                        last={d.lastAssistant()?.id === message.id}
                        message={message as AssistantMessage}
                        parts={d.sync.data.part[message.id] ?? []}
                      />
                    </Match>
                  </Switch>
                )}
              </For>
            </scrollbox>
            <box flexShrink={0}>
              <Show when={d.permissions().length > 0}>
                <PermissionPrompt request={d.permissions()[0]} />
              </Show>
              <Show when={d.permissions().length === 0 && d.question()} keyed>
                {(request: any) => <QuestionPrompt request={request} nonBlocking={request.blocking === false} inputFocused={() => promptRef.current?.focused ?? false} />}
              </Show>
              <Show when={d.permissions().length === 0 && !d.question()}>
                <Show when={d.blockingSuggestion()} keyed>
                  {(request: any) => <SuggestPrompt request={request} />}
                </Show>
              </Show>
              <Show when={d.session()?.parentID}>
                <SubagentFooter />
              </Show>
              <Show when={d.networkVisible()}>
                <NetworkPrompt request={d.network()[0]} />
              </Show>
              <Show when={!d.session()?.parentID}>
                <TuiPluginRuntime.Slot name="session_prompt" mode="replace" session_id={d.sessionID} visible={d.visible()} disabled={d.disabled()} on_submit={d.toBottom} ref={d.promptBind}>
                  <Prompt
                    visible={d.visible()}
                    ref={d.promptBind}
                    disabled={d.disabled()}
                    onSubmit={() => d.toBottom()}
                    sessionID={d.sessionID}
                    right={
                      <box flexDirection="row" gap={1} alignItems="center">
                        <text fg={theme.textMuted} onMouseDown={() => { const vis = d.sidebarVisible(); d.setSidebar(() => (vis ? "hide" : "auto")); d.setSidebarOpen(!vis) }}>
                          {d.sidebarVisible() ? "◂" : "▸"}
                        </text>
                        <text fg={theme.textMuted} onMouseDown={() => d.toBottom()}>↓</text>
                        <TuiPluginRuntime.Slot name="session_prompt_right" session_id={d.sessionID} />
                      </box>
                    }
                  />
                </TuiPluginRuntime.Slot>
              </Show>
            </box>
          </Show>
          <SessionIndexing />
          <Toast />
        </box>
        <Show when={d.sidebarVisible()}>
          <Switch>
            <Match when={d.wide()}>
              <Sidebar sessionID={d.sessionID} />
            </Match>
            <Match when={!d.wide()}>
              <box position="absolute" top={0} left={0} right={0} bottom={0} alignItems="flex-end" backgroundColor={RGBA.fromInts(0, 0, 0, 70)}>
                <Sidebar sessionID={d.sessionID} />
              </box>
            </Match>
          </Switch>
        </Show>
      </box>
    </context.Provider>
  )
}
