'use client'

import { memo, type ReactNode } from 'react'
import { Handle, Position, type NodeProps } from '@xyflow/react'
import { cn } from '@/lib/utils'
import {
  NODE_COLORS,
  CONDITION_OPERATORS,
  LABEL_CONDITION_OPERATORS,
} from '@/lib/mail-automation/node-definitions'
import { actionTypeLabel, conditionFieldLabel } from '@/lib/mail-automation/domains'
import { formatConditionSummary } from '@/lib/mail-automation/condition-helpers'
import type {
  ActionsNodeData,
  ConditionNodeData,
  LabelCheckNodeData,
  LLMCheckNodeData,
  SetVarNodeData,
  SwitchNodeData,
  CallRuleNodeData,
  WorkflowNodeType,
} from '@/lib/mail-automation/types'

function fieldLabel(field: string) {
  return conditionFieldLabel(field)
}

function opLabel(op: string) {
  const fromString = CONDITION_OPERATORS.find((o) => o.value === op)?.label
  if (fromString) return fromString
  return LABEL_CONDITION_OPERATORS.find((o) => o.value === op)?.label ?? op
}

function actionLabel(type: string) {
  return actionTypeLabel(type)
}

function nodeShell(
  type: WorkflowNodeType,
  selected: boolean | undefined,
  className: string,
  children: ReactNode
) {
  return (
    <div
      className={cn(
        'rounded-lg border-2 px-3 py-2 shadow-sm transition-shadow',
        NODE_COLORS[type],
        selected && 'border-primary ring-2 ring-primary/40 shadow-md',
        className
      )}
    >
      {children}
    </div>
  )
}

function BranchOutputRow({
  id,
  label,
  labelClassName,
  handleClassName,
  top,
}: {
  id: string
  label: string
  labelClassName?: string
  handleClassName?: string
  top: string
}) {
  return (
    <>
      <span
        className={cn(
          'pointer-events-none absolute right-5 -translate-y-1/2 text-[10px] font-medium',
          labelClassName
        )}
        style={{ top }}
      >
        {label}
      </span>
      <Handle
        type="source"
        position={Position.Right}
        id={id}
        style={{ top }}
        className={cn('!size-2.5', handleClassName)}
      />
    </>
  )
}

function BranchOutputs({
  branches,
}: {
  branches: {
    id: string
    label: string
    labelClassName?: string
    handleClassName?: string
  }[]
}) {
  const rowHeight = 24
  const blockHeight = branches.length * rowHeight

  return (
    <div
      className="relative mt-3 border-t border-border/40 pt-2"
      style={{ height: blockHeight }}
    >
      {branches.map((b, i) => {
        const topPx = rowHeight * i + rowHeight / 2
        return <BranchOutputRow key={b.id} {...b} top={`${topPx}px`} />
      })}
    </div>
  )
}

export const StartNode = memo(function StartNode({ selected }: NodeProps) {
  return nodeShell('start', selected, 'min-w-[120px]', (
    <>
      <p className="text-xs font-semibold">Début</p>
      <Handle type="source" position={Position.Right} className="!size-2.5 !bg-primary" />
    </>
  ))
})

export const EndNode = memo(function EndNode({ selected }: NodeProps) {
  return nodeShell('end', selected, 'min-w-[100px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold text-muted-foreground">Fin</p>
    </>
  ))
})

export const ConditionNode = memo(function ConditionNode({ data, selected }: NodeProps) {
  const d = data as unknown as ConditionNodeData
  return nodeShell('condition', selected, 'min-w-[200px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Si…</p>
      <p className="mt-1 text-[11px] text-muted-foreground">
        {formatConditionSummary(d, fieldLabel, opLabel)}
      </p>
      <BranchOutputs
        branches={[
          { id: 'true', label: 'vrai', labelClassName: 'text-emerald-600', handleClassName: '!bg-emerald-500' },
          { id: 'false', label: 'faux', labelClassName: 'text-rose-600', handleClassName: '!bg-rose-500' },
        ]}
      />
    </>
  ))
})

export const LabelCheckNode = memo(function LabelCheckNode({ data, selected }: NodeProps) {
  const d = data as unknown as LabelCheckNodeData
  return nodeShell('label_check', selected, 'min-w-[200px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Libellé</p>
      <p className="mt-1 text-[11px] text-muted-foreground">
        {d.operator === 'not_has' ? 'Sans' : 'A'} « {d.label || '…'} »
      </p>
      <BranchOutputs
        branches={[
          { id: 'true', label: 'vrai', labelClassName: 'text-emerald-600', handleClassName: '!bg-emerald-500' },
          { id: 'false', label: 'faux', labelClassName: 'text-rose-600', handleClassName: '!bg-rose-500' },
        ]}
      />
    </>
  ))
})

export const SwitchNode = memo(function SwitchNode({ data, selected }: NodeProps) {
  const d = data as unknown as SwitchNodeData
  const cases = d.cases ?? []
  const caseBranches = cases.map((c, i) => ({
    id: `case-${i}`,
    label: c.label || c.value || `Cas ${i + 1}`,
    labelClassName: 'text-violet-600',
    handleClassName: '!bg-violet-500',
  }))

  return nodeShell('switch', selected, 'min-w-[220px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Switch · {fieldLabel(d.field)}</p>
      <BranchOutputs
        branches={[
          ...caseBranches,
          {
            id: 'default',
            label: 'défaut',
            labelClassName: 'text-muted-foreground',
            handleClassName: '!bg-muted-foreground',
          },
        ]}
      />
    </>
  ))
})

export const LLMCheckNode = memo(function LLMCheckNode({ data, selected }: NodeProps) {
  const d = data as unknown as LLMCheckNodeData
  return nodeShell('llm_check', selected, 'min-w-[220px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">LLM</p>
      <p className="mt-1 line-clamp-2 text-[11px] text-muted-foreground">{d.prompt || 'Prompt…'}</p>
      <BranchOutputs
        branches={[
          { id: 'true', label: 'vrai', labelClassName: 'text-emerald-600', handleClassName: '!bg-emerald-500' },
          { id: 'false', label: 'faux', labelClassName: 'text-rose-600', handleClassName: '!bg-rose-500' },
        ]}
      />
    </>
  ))
})

export const ActionsNode = memo(function ActionsNode({ data, selected }: NodeProps) {
  const d = data as unknown as ActionsNodeData
  const actions = d.actions ?? []
  return nodeShell('actions', selected, 'min-w-[200px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Actions ({actions.length})</p>
      <ul className="mt-1 space-y-0.5 text-[11px] text-muted-foreground">
        {actions.slice(0, 4).map((a, i) => (
          <li key={i}>
            {actionLabel(a.type)}
            {a.value ? `: ${a.value}` : ''}
          </li>
        ))}
      </ul>
      <Handle type="source" position={Position.Right} className="!size-2.5 !bg-primary" />
    </>
  ))
})

export const SetVarNode = memo(function SetVarNode({ data, selected }: NodeProps) {
  const d = data as unknown as SetVarNodeData
  return nodeShell('set_var', selected, 'min-w-[180px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Variable</p>
      <p className="mt-1 font-mono text-[11px] text-muted-foreground">
        {d.name || 'var'} = {d.value || '…'}
      </p>
      <Handle type="source" position={Position.Right} className="!size-2.5 !bg-primary" />
    </>
  ))
})

export const CallFunctionNode = memo(function CallFunctionNode({ data, selected }: NodeProps) {
  const d = data as unknown as CallRuleNodeData
  return nodeShell('call_function', selected, 'min-w-[180px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Fonction</p>
      <p className="mt-1 truncate text-[11px] text-muted-foreground">{d.rule_id || 'Choisir…'}</p>
      <Handle type="source" position={Position.Right} className="!size-2.5 !bg-primary" />
    </>
  ))
})

export const CallRuleNode = memo(function CallRuleNode({ data, selected }: NodeProps) {
  const d = data as unknown as CallRuleNodeData
  return nodeShell('call_rule', selected, 'min-w-[180px]', (
    <>
      <Handle type="target" position={Position.Left} className="!size-2.5 !bg-primary" />
      <p className="text-xs font-semibold">Règle cascade</p>
      <p className="mt-1 truncate text-[11px] text-muted-foreground">{d.rule_id || 'Choisir…'}</p>
      <Handle type="source" position={Position.Right} className="!size-2.5 !bg-primary" />
    </>
  ))
})

export const workflowNodeTypes = {
  start: StartNode,
  end: EndNode,
  condition: ConditionNode,
  label_check: LabelCheckNode,
  switch: SwitchNode,
  llm_check: LLMCheckNode,
  actions: ActionsNode,
  set_var: SetVarNode,
  call_function: CallFunctionNode,
  call_rule: CallRuleNode,
}
