import { Collapsible } from "@kobalte/core/collapsible"
import { type ComponentProps, type JSX, For, Show, createMemo, splitProps } from "solid-js"
import { DiffChanges } from "@opencode-ai/ui/v2/diff-changes-v2"
import { TextShimmerV2 } from "@opencode-ai/ui/v2/text-shimmer-v2"
import "./basic-tool-v2.css"

function ChevronIcon() {
  return (
    <svg
      data-slot="basic-tool-v2-chevron"
      width="16"
      height="16"
      viewBox="0 0 16 16"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
    >
      <path
        d="M6.75194 10.6243C6.41861 10.8187 6 10.5783 6 10.1924V5.80837C6 5.42247 6.41861 5.18204 6.75194 5.37648L10.5096 7.56846C10.8404 7.7614 10.8404 8.2393 10.5096 8.43224L6.75194 10.6243Z"
        fill="currentColor"
      />
    </svg>
  )
}

export interface BasicToolV2TriggerTitle {
  title: string
  subtitle?: string
  args?: string[]
  changes?: { additions: number; deletions: number } | { additions: number; deletions: number }[]
  action?: JSX.Element
}

const isTriggerTitle = (val: unknown): val is BasicToolV2TriggerTitle =>
  typeof val === "object" && val !== null && "title" in val && (typeof Node === "undefined" || !(val instanceof Node))

export interface BasicToolV2Props extends Omit<ComponentProps<"div">, "children" | "title"> {
  trigger: BasicToolV2TriggerTitle | JSX.Element
  children?: JSX.Element
  status?: string
  open?: boolean
  defaultOpen?: boolean
  onOpenChange?: (open: boolean) => void
  onSubtitleClick?: () => void
}

export function BasicToolV2(props: BasicToolV2Props) {
  const [local, rest] = splitProps(props, [
    "trigger",
    "children",
    "status",
    "open",
    "defaultOpen",
    "onOpenChange",
    "onSubtitleClick",
    "class",
    "classList",
  ])

  const pending = createMemo(() => local.status === "pending" || local.status === "running")

  const hasChildren = createMemo(() => {
    const c = local.children
    if (c == null) return false
    return true
  })

  const canExpand = createMemo(() => hasChildren() && !pending())

  const handleOpenChange = (value: boolean) => {
    if (pending()) return
    local.onOpenChange?.(value)
  }

  return (
    <Collapsible
      {...rest}
      data-component="basic-tool-v2"
      open={local.open}
      defaultOpen={local.defaultOpen}
      onOpenChange={handleOpenChange}
      disabled={!canExpand()}
      classList={{
        ...local.classList,
        [local.class ?? ""]: !!local.class,
      }}
    >
      <Collapsible.Trigger as="div" role="button" data-slot="basic-tool-v2-trigger">
        <div data-slot="basic-tool-v2-labels">
          <Show when={isTriggerTitle(local.trigger) && local.trigger} fallback={local.trigger as JSX.Element}>
            {(title) => (
              <>
                <span data-slot="basic-tool-v2-title">
                  <TextShimmerV2 text={title().title} active={pending()} />
                </span>
                <Show when={!pending() && title().subtitle}>
                  <span data-slot="basic-tool-v2-sep" aria-hidden="true">
                    ·
                  </span>
                  <span
                    data-slot="basic-tool-v2-subtitle"
                    style={local.onSubtitleClick ? { cursor: "pointer" } : undefined}
                    onClick={(e) => {
                      if (local.onSubtitleClick) {
                        e.stopPropagation()
                        local.onSubtitleClick()
                      }
                    }}
                  >
                    {title().subtitle}
                  </span>
                </Show>
                <Show when={!pending() && title().args?.length}>
                  <For each={title().args}>{(arg) => <span data-slot="basic-tool-v2-arg">{arg}</span>}</For>
                </Show>
                <Show when={!pending() && title().changes}>
                  <span data-slot="basic-tool-v2-diff">
                    <DiffChanges changes={title().changes!} />
                  </span>
                </Show>
                <Show when={!pending() && title().action}>{(action) => action()}</Show>
              </>
            )}
          </Show>
          <Show when={canExpand()}>
            <span data-slot="basic-tool-v2-chevron-wrap">
              <ChevronIcon />
            </span>
          </Show>
        </div>
      </Collapsible.Trigger>
      <Show when={canExpand()}>
        <Collapsible.Content data-slot="basic-tool-v2-content">
          <div data-slot="basic-tool-v2-content-inner">{local.children}</div>
        </Collapsible.Content>
      </Show>
    </Collapsible>
  )
}
