"use client"

import { useState } from "react"
import type { Node } from "@xyflow/react"

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import { OptionCombobox } from "@/components/option-combobox"
import { VariableSelector } from "./variable-selector"
import type {
  WorkflowConditionBranch,
  WorkflowNodeSpec,
  WorkflowNodeConfig,
  WorkflowVariableRef,
  WorkflowVariableSpec,
  WorkflowVariableSelector,
} from "./workflow-utils"

type WorkflowNodeData = Record<string, unknown> & {
  nodeType?: string
  name?: string
  title?: string
  config?: WorkflowNodeConfig
  inputs?: Record<string, WorkflowVariableSelector>
}

export type WorkflowBranchSummary = {
  branchId: string
  targetNodeId: string
  targetName: string
  conditionLabel: string
  isDefault: boolean
}

export function NodeConfigPanel({
  node,
  nodeSpec,
  availableVariables,
  branchSummaries = [],
  onChange,
}: {
  node: Node<WorkflowNodeData> | null
  nodeSpec?: WorkflowNodeSpec
  availableVariables: WorkflowVariableRef[]
  branchSummaries?: WorkflowBranchSummary[]
  onChange: (nodeId: string, data: WorkflowNodeData) => void
}) {
  if (!node) {
    return (
      <div className="flex h-full items-center justify-center px-4 text-sm text-muted-foreground">
        选择一个节点后，可以配置输入映射并查看输出变量。
      </div>
    )
  }

  return (
    <NodeConfigForm
      key={node.id}
      node={node}
      nodeSpec={nodeSpec}
      availableVariables={availableVariables}
      branchSummaries={branchSummaries}
      onChange={onChange}
    />
  )
}

function NodeConfigForm({
  node,
  nodeSpec,
  availableVariables,
  branchSummaries,
  onChange,
}: {
  node: Node<WorkflowNodeData>
  nodeSpec?: WorkflowNodeSpec
  availableVariables: WorkflowVariableRef[]
  branchSummaries: WorkflowBranchSummary[]
  onChange: (nodeId: string, data: WorkflowNodeData) => void
}) {
  const [name, setName] = useState(node.data.name ?? "")
  const [configText, setConfigText] = useState(JSON.stringify(node.data.config ?? {}, null, 2))
  const [inputs, setInputs] = useState<Record<string, WorkflowVariableSelector>>(
    node.data.inputs ?? {}
  )
  const [error, setError] = useState("")
  const inputSchema = nodeSpec?.inputSchema ?? []
  const outputSchema = nodeSpec?.outputSchema ?? []
  const isConditionNode = node.data.nodeType === "condition"
  const fallbackNodeName = nodeSpec?.title || node.data.title || node.data.nodeType || node.id
  const panelTitle = name.trim() || node.data.name?.trim() || fallbackNodeName

  const commitChange = (next: Partial<WorkflowNodeData>) => {
    onChange(node.id, {
      ...node.data,
      name: name.trim() || fallbackNodeName,
      config: node.data.config ?? {},
      inputs,
      ...next,
    })
  }

  const handleApply = () => {
    try {
      const parsed = JSON.parse(configText || "{}") as Record<string, unknown>
      setError("")
      commitChange({ config: parsed })
    } catch {
      setError("Config must be valid JSON.")
    }
  }

  return (
    <div className="flex h-full min-h-0 flex-col gap-4 p-4">
      <div>
        <div className="text-sm font-medium">{panelTitle}</div>
        <div className="mt-1 text-xs text-muted-foreground">
          {node.data.nodeType && node.data.nodeType !== panelTitle
            ? `${node.id} · ${node.data.nodeType}`
            : node.id}
        </div>
      </div>
      <div className="space-y-2">
        <Label htmlFor="workflow-node-name">节点名称</Label>
        <Input
          id="workflow-node-name"
          value={name}
          onChange={(event) => setName(event.target.value)}
          onBlur={() => commitChange({ name: name.trim() || node.data.nodeType || node.id })}
        />
      </div>
      {isConditionNode ? (
        <ConditionNodePanel
          branches={node.data.config?.branches ?? []}
          branchSummaries={branchSummaries}
          availableVariables={availableVariables}
          outputSchema={outputSchema}
          onChange={(branches) => commitChange({ config: { ...(node.data.config ?? {}), branches } })}
        />
      ) : (
        <>
          {inputSchema.length > 0 ? (
            <div className="space-y-3">
              <div className="text-sm font-medium">输入映射</div>
              {availableVariables.length === 0 ? (
                <div className="rounded-md border border-dashed p-2 text-xs text-muted-foreground">
                  当前节点前面还没有可用变量，请先连接上游节点。
                </div>
              ) : null}
              {inputSchema.map((input) => (
                <div key={input.name} className="space-y-1.5">
                  <div className="flex items-center justify-between gap-2">
                    <Label className="text-xs">
                      {input.name}
                      {input.required ? <span className="text-destructive"> *</span> : null}
                    </Label>
                    <span className="text-xs text-muted-foreground">{input.type}</span>
                  </div>
                  <VariableSelector
                    value={inputs[input.name]}
                    variables={availableVariables}
                    onChange={(value) => {
                      const nextInputs = {
                        ...inputs,
                        [input.name]: value,
                      }
                      setInputs(nextInputs)
                      commitChange({
                        inputs: nextInputs,
                      })
                    }}
                  />
                  {inputs[input.name] ? (
                    <div className="text-xs text-muted-foreground">
                      已选择：{inputs[input.name].nodeId}.{inputs[input.name].field}
                    </div>
                  ) : null}
                  {input.description ? (
                    <div className="text-xs text-muted-foreground">{input.description}</div>
                  ) : null}
                </div>
              ))}
            </div>
          ) : null}
          <details className="rounded-md border bg-background p-3">
            <summary className="cursor-pointer text-sm font-medium">高级配置 JSON</summary>
            <div className="mt-3 space-y-2">
              <Textarea
                id="workflow-node-config"
                className="h-40 font-mono text-xs"
                value={configText}
                onChange={(event) => setConfigText(event.target.value)}
              />
              {error ? <div className="text-xs text-destructive">{error}</div> : null}
              <Button type="button" variant="outline" size="sm" onClick={handleApply}>
                保存高级配置
              </Button>
            </div>
          </details>
          {outputSchema.length > 0 ? (
            <div className="space-y-2">
              <div className="text-sm font-medium">输出变量</div>
              <div className="space-y-1 rounded-md border bg-background p-2">
                {outputSchema.map((output) => (
                  <div key={output.name} className="space-y-0.5 rounded-sm px-1 py-0.5">
                    <div className="flex items-center justify-between gap-2 text-xs">
                      <span className="truncate font-medium">{output.name}</span>
                      <span className="shrink-0 text-muted-foreground">{output.type}</span>
                    </div>
                    {output.description ? (
                      <div className="text-xs text-muted-foreground">{output.description}</div>
                    ) : null}
                  </div>
                ))}
              </div>
            </div>
          ) : null}
        </>
      )}
    </div>
  )
}

function ConditionNodePanel({
  branches,
  branchSummaries,
  availableVariables,
  outputSchema,
  onChange,
}: {
  branches: WorkflowConditionBranch[]
  branchSummaries: WorkflowBranchSummary[]
  availableVariables: WorkflowVariableRef[]
  outputSchema: WorkflowVariableSpec[]
  onChange: (branches: WorkflowConditionBranch[]) => void
}) {
  const summariesByBranchID = new Map(branchSummaries.map((item) => [item.branchId, item]))
  const commitBranch = (branchId: string, patch: Partial<WorkflowConditionBranch>) => {
    onChange(branches.map((branch) => (
      branch.id === branchId ? normalizeBranch({ ...branch, ...patch }) : branch
    )))
  }
  const addBranch = () => {
    const index = branches.length + 1
    const nextBranch = {
      id: `branch_${index}`,
      name: `分支 ${index}`,
      targetNodeId: "",
      condition: { operator: "eq" },
    }
    const defaultIndex = branches.findIndex((branch) => branch.default)
    if (defaultIndex >= 0) {
      onChange([
        ...branches.slice(0, defaultIndex),
        nextBranch,
        ...branches.slice(defaultIndex),
      ])
      return
    }
    onChange([
      ...branches,
      nextBranch,
      {
        id: "default",
        name: "其他情况",
        targetNodeId: "",
        default: true,
      },
    ])
  }
  const deleteBranch = (branchId: string) => {
    onChange(branches.filter((branch) => branch.id !== branchId || branch.default))
  }
  const moveBranch = (branchId: string, direction: -1 | 1) => {
    const index = branches.findIndex((branch) => branch.id === branchId)
    if (index < 0 || branches[index]?.default) {
      return
    }
    const nextIndex = index + direction
    if (nextIndex < 0 || nextIndex >= branches.length || branches[nextIndex]?.default) {
      return
    }
    const next = [...branches]
    const current = next[index]
    next[index] = next[nextIndex]
    next[nextIndex] = current
    onChange(next)
  }

  return (
    <>
      <div className="space-y-2">
        <div className="flex items-center justify-between gap-2">
          <div className="text-sm font-medium">分支</div>
          <Button type="button" variant="outline" size="sm" onClick={addBranch}>
            添加分支
          </Button>
        </div>
        {branches.length > 0 ? (
          <div className="space-y-2">
            {branches.map((branch, index) => {
              const summary = summariesByBranchID.get(branch.id)
              const condition = branch.condition ?? {}
              const selectedVariable = findConditionVariable(availableVariables, condition.left)
              const operatorOptions = getConditionOperatorOptions(selectedVariable)
              const conditionRight = condition.right === undefined || condition.right === null
                ? ""
                : String(condition.right)
              return (
                <div key={branch.id} className="space-y-3 rounded-md border bg-background p-3">
                  <div className="flex items-center justify-between gap-2 text-xs">
                    <span className="min-w-0 truncate font-medium">
                      {branch.default ? "ELSE" : index === 0 ? "IF" : "ELSE IF"}
                    </span>
                    <span className="shrink-0 rounded-sm bg-muted px-1.5 py-0.5 text-muted-foreground">
                      {branch.default ? "默认" : "条件"}
                    </span>
                  </div>
                  <div className="space-y-1.5">
                    <Label className="text-xs">分支名称</Label>
                    <Input
                      value={branch.name ?? ""}
                      onChange={(event) => commitBranch(branch.id, { name: event.target.value })}
                      placeholder="例如：需要转人工"
                    />
                  </div>
                  <div className="space-y-1.5">
                    <Label className="text-xs">目标节点</Label>
                    <div className="rounded-md border border-dashed bg-muted/20 px-2 py-2 text-xs text-muted-foreground">
                      {summary?.targetNodeId
                        ? `已连接到：${summary.targetName}`
                        : "请从画布中该分支右侧连接点拖线到目标节点"}
                    </div>
                  </div>
                  {branch.default ? (
                    <div className="rounded-md border border-dashed p-2 text-xs text-muted-foreground">
                      未命中上方条件时进入：{summary?.targetName ?? (branch.targetNodeId || "未选择目标节点")}
                    </div>
                  ) : (
                    <div className="space-y-3 rounded-md border bg-muted/20 p-2">
                      <div className="space-y-1.5">
                        <Label className="text-xs">判断变量</Label>
                        <VariableSelector
                          value={condition.left}
                          variables={availableVariables}
                          onChange={(value) => commitBranch(branch.id, {
                            condition: { ...condition, left: value },
                          })}
                        />
                      </div>
                      <div className="space-y-1.5">
                        <Label className="text-xs">判断方式</Label>
                        <OptionCombobox
                          value={condition.operator ?? "eq"}
                          options={operatorOptions}
                          placeholder="选择判断方式"
                          searchPlaceholder="搜索判断方式"
                          emptyText="没有可用判断方式"
                          onChange={(value) => commitBranch(branch.id, {
                            condition: { ...condition, operator: value },
                          })}
                        />
                      </div>
                      {!conditionOperatorWithoutRight(condition.operator ?? "eq") ? (
                        <ConditionRightControl
                          value={conditionRight}
                          variable={selectedVariable}
                          onChange={(right) => commitBranch(branch.id, {
                            condition: { ...condition, right },
                          })}
                        />
                      ) : null}
                    </div>
                  )}
                  <div className="flex flex-wrap gap-2">
                    {!branch.default && index > 0 ? (
                      <Button type="button" size="sm" variant="outline" onClick={() => moveBranch(branch.id, -1)}>
                        上移
                      </Button>
                    ) : null}
                    {!branch.default && index < branches.findIndex((item) => item.default) - 1 ? (
                      <Button type="button" size="sm" variant="outline" onClick={() => moveBranch(branch.id, 1)}>
                        下移
                      </Button>
                    ) : null}
                    {!branch.default ? (
                      <Button type="button" size="sm" variant="outline" onClick={() => deleteBranch(branch.id)}>
                        删除
                      </Button>
                    ) : null}
                  </div>
                  <div className="line-clamp-2 text-xs text-muted-foreground">
                    {summary?.conditionLabel ?? "尚未完成分支配置"}
                  </div>
                </div>
              )
            })}
          </div>
        ) : (
          <div className="rounded-md border border-dashed p-2 text-xs text-muted-foreground">
            当前还没有分支。
          </div>
        )}
      </div>
      {outputSchema.length > 0 ? (
        <div className="space-y-2">
          <div className="text-sm font-medium">输出变量</div>
          <div className="space-y-1 rounded-md border bg-background p-2">
            {outputSchema.map((output) => (
              <div key={output.name} className="space-y-0.5 rounded-sm px-1 py-0.5">
                <div className="flex items-center justify-between gap-2 text-xs">
                  <span className="truncate font-medium">{output.name}</span>
                  <span className="shrink-0 text-muted-foreground">{output.type}</span>
                </div>
                {output.description ? (
                  <div className="text-xs text-muted-foreground">{output.description}</div>
                ) : null}
              </div>
            ))}
          </div>
        </div>
      ) : null}
    </>
  )
}

const conditionOperators = [
  { value: "eq", label: "等于" },
  { value: "neq", label: "不等于" },
  { value: "contains", label: "包含" },
  { value: "exists", label: "存在" },
  { value: "not_exists", label: "不存在" },
  { value: "truthy", label: "为真" },
  { value: "is_true", label: "为真" },
  { value: "falsy", label: "为假" },
  { value: "is_false", label: "为假" },
  { value: "gt", label: "大于" },
  { value: "gte", label: "大于等于" },
  { value: "lt", label: "小于" },
  { value: "lte", label: "小于等于" },
]

function ConditionRightControl({
  value,
  variable,
  onChange,
}: {
  value: string
  variable?: WorkflowVariableRef
  onChange: (value: unknown) => void
}) {
  const valueOptions = getConditionValueOptions(variable)
  if (valueOptions.length > 0) {
    return (
      <div className="space-y-1.5">
        <Label className="text-xs">比较值</Label>
        <OptionCombobox
          value={value}
          options={valueOptions}
          placeholder="选择比较值"
          searchPlaceholder="搜索比较值"
          emptyText="当前变量没有可选值"
          onChange={(nextValue) => onChange(decodeConditionRight(nextValue, variable))}
        />
      </div>
    )
  }

  return (
    <div className="space-y-1.5">
      <Label className="text-xs">比较值</Label>
      <Input
        type={variable?.type === "number" || variable?.type === "integer" ? "number" : "text"}
        value={value}
        onChange={(event) => onChange(normalizeConditionRight(event.target.value, variable))}
        placeholder={variable ? `请输入${variable.label || variable.field}的比较值` : "请输入比较值"}
      />
    </div>
  )
}

function conditionOperatorWithoutRight(operator: string) {
  return ["exists", "not_exists", "truthy", "is_true", "falsy", "is_false"].includes(operator)
}

function normalizeConditionRight(value: string, variable?: WorkflowVariableRef) {
  const trimmed = value.trim()
  if (variable?.type === "boolean") {
    return trimmed === "true"
  }
  if (variable?.type === "number" || variable?.type === "integer") {
    return trimmed === "" ? "" : Number(trimmed)
  }
  if (variable?.type === "string") {
    return trimmed
  }
  if (trimmed === "true") return true
  if (trimmed === "false") return false
  if (trimmed !== "" && !Number.isNaN(Number(trimmed))) return Number(trimmed)
  return trimmed
}

function findConditionVariable(
  variables: WorkflowVariableRef[],
  selector?: WorkflowVariableSelector
): WorkflowVariableRef | undefined {
  if (!selector?.nodeId || !selector.field) {
    return undefined
  }
  return variables.find((item) => item.nodeId === selector.nodeId && item.field === selector.field)
}

function getConditionOperatorOptions(variable?: WorkflowVariableRef) {
  if (!variable?.operators?.length) {
    return conditionOperators
  }
  const allowed = new Set(variable.operators)
  return conditionOperators.filter((item) => allowed.has(item.value))
}

function getConditionValueOptions(variable?: WorkflowVariableRef) {
  if (variable?.valueOptions?.length) {
    return variable.valueOptions.map((item) => ({
      value: encodeConditionRight(item.value),
      label: item.label,
    }))
  }
  if (variable?.type === "boolean") {
    return [
      { value: "true", label: "是" },
      { value: "false", label: "否" },
    ]
  }
  return []
}

function encodeConditionRight(value: unknown) {
  if (typeof value === "string") return value
  if (typeof value === "number" || typeof value === "boolean") return String(value)
  return JSON.stringify(value)
}

function decodeConditionRight(value: string, variable?: WorkflowVariableRef) {
  if (variable?.type === "boolean") {
    return value === "true"
  }
  if (variable?.type === "number" || variable?.type === "integer") {
    return Number(value)
  }
  const option = variable?.valueOptions?.find((item) => encodeConditionRight(item.value) === value)
  return option ? option.value : value
}

function normalizeBranch(branch: WorkflowConditionBranch): WorkflowConditionBranch {
  if (branch.default) {
    const { condition: _condition, ...rest } = branch
    return rest
  }
  return {
    ...branch,
    condition: branch.condition ?? { operator: "eq" },
  }
}
