'use client'

import { useCallback, useMemo, useState, ChangeEvent } from 'react'
import { Handle, Position, NodeProps, useReactFlow } from 'reactflow'
import { nanoid } from 'nanoid'
import { useEditorContext } from '@/components/editor/EditorContext'
import OptionConditionEditor from '@/components/editor/OptionConditionEditor'
import type { Condition } from '@/types/flowchart'

type ChoiceOption = {
  id: string
  label: string
  condition?: Condition
}

type ChoiceNodeData = {
  prompt: string
  options: ChoiceOption[]
}

const MIN_OPTIONS = 2
const MAX_OPTIONS = 6

export default function ChoiceNode({ id, data }: NodeProps<ChoiceNodeData>) {
  const { setNodes } = useReactFlow()
  const [editingConditionOptionId, setEditingConditionOptionId] = useState<string | null>(null)

  const updatePrompt = useCallback(
    (e: ChangeEvent<HTMLInputElement>) => {
      setNodes((nodes) =>
        nodes.map((node) =>
          node.id === id
            ? { ...node, data: { ...node.data, prompt: e.target.value } }
            : node
        )
      )
    },
    [id, setNodes]
  )

  const updateOptionLabel = useCallback(
    (optionId: string, label: string) => {
      setNodes((nodes) =>
        nodes.map((node) =>
          node.id === id
            ? {
                ...node,
                data: {
                  ...node.data,
                  options: node.data.options.map((opt: ChoiceOption) =>
                    opt.id === optionId ? { ...opt, label } : opt
                  ),
                },
              }
            : node
        )
      )
    },
    [id, setNodes]
  )

  const updateOptionCondition = useCallback(
    (optionId: string, condition: Condition | undefined) => {
      setNodes((nodes) =>
        nodes.map((node) =>
          node.id === id
            ? {
                ...node,
                data: {
                  ...node.data,
                  options: node.data.options.map((opt: ChoiceOption) =>
                    opt.id === optionId ? { ...opt, condition } : opt
                  ),
                },
              }
            : node
        )
      )
    },
    [id, setNodes]
  )

  const addOption = useCallback(() => {
    if (data.options.length >= MAX_OPTIONS) return
    setNodes((nodes) =>
      nodes.map((node) =>
        node.id === id
          ? {
              ...node,
              data: {
                ...node.data,
                options: [
                  ...node.data.options,
                  { id: nanoid(), label: '' },
                ],
              },
            }
          : node
      )
    )
  }, [id, data.options.length, setNodes])

  const removeOption = useCallback(
    (optionId: string) => {
      if (data.options.length <= MIN_OPTIONS) return
      setNodes((nodes) =>
        nodes.map((node) =>
          node.id === id
            ? {
                ...node,
                data: {
                  ...node.data,
                  options: node.data.options.filter(
                    (opt: ChoiceOption) => opt.id !== optionId
                  ),
                },
              }
            : node
        )
      )
    },
    [id, data.options.length, setNodes]
  )

  const editingOption = useMemo(() => {
    if (!editingConditionOptionId) return null
    return data.options.find((opt) => opt.id === editingConditionOptionId) || null
  }, [editingConditionOptionId, data.options])

  const hasInvalidConditionReference = useCallback(
    (option: ChoiceOption) => {
      if (!option.condition?.variableId) return false
      return !variables.some((v) => v.id === option.condition!.variableId)
    },
    [variables]
  )

  return (
    <>
      <div className="min-w-[220px] rounded-lg border-2 border-green-500 bg-green-50 p-3 shadow-md dark:border-green-400 dark:bg-green-950">
        <Handle
          type="target"
          position={Position.Top}
          id="input"
          className="!h-3 !w-3 !border-2 !border-green-500 !bg-white dark:!bg-zinc-800"
        />

        <div className="mb-2 text-xs font-semibold uppercase tracking-wide text-green-700 dark:text-green-300">
          Choice
        </div>

        <input
          type="text"
          value={data.prompt || ''}
          onChange={updatePrompt}
          placeholder="What do you choose?"
          className="mb-3 w-full rounded border border-green-300 bg-white px-2 py-1 text-sm focus:border-green-500 focus:outline-none focus:ring-1 focus:ring-green-500 dark:border-green-600 dark:bg-zinc-800 dark:text-white dark:placeholder-zinc-400"
        />

        <div className="space-y-2">
          {data.options.map((option, index) => (
            <div key={option.id}>
              <div className="relative flex items-center gap-1">
                <input
                  type="text"
                  value={option.label}
                  onChange={(e) => updateOptionLabel(option.id, e.target.value)}
                  placeholder={`Option ${index + 1}`}
                  className="flex-1 rounded border border-green-300 bg-white px-2 py-1 text-sm focus:border-green-500 focus:outline-none focus:ring-1 focus:ring-green-500 dark:border-green-600 dark:bg-zinc-800 dark:text-white dark:placeholder-zinc-400"
                />
                <button
                  type="button"
                  onClick={() => setEditingConditionOptionId(option.id)}
                  className={`flex h-6 w-6 items-center justify-center rounded text-xs ${
                    option.condition?.variableId
                      ? hasInvalidConditionReference(option)
                        ? 'bg-orange-100 text-orange-600 ring-1 ring-orange-500 dark:bg-orange-900/30 dark:text-orange-400'
                        : 'bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400'
                      : 'text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-700'
                  }`}
                  title={option.condition?.variableId ? 'Edit condition' : 'Add condition'}
                >
                  <svg className="h-3.5 w-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
                  </svg>
                </button>
                <button
                  type="button"
                  onClick={() => removeOption(option.id)}
                  disabled={data.options.length <= MIN_OPTIONS}
                  className="flex h-6 w-6 items-center justify-center rounded text-red-500 hover:bg-red-100 disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent dark:hover:bg-red-900/30"
                  title="Remove option"
                >
                  ×
                </button>
                <Handle
                  type="source"
                  position={Position.Bottom}
                  id={`option-${index}`}
                  className="!h-3 !w-3 !border-2 !border-green-500 !bg-white dark:!bg-zinc-800"
                  style={{
                    left: `${((index + 1) / (data.options.length + 1)) * 100}%`,
                  }}
                />
              </div>
              {option.condition?.variableId && (
                <div className={`mt-0.5 ml-1 text-[10px] ${
                  hasInvalidConditionReference(option)
                    ? 'text-orange-500 dark:text-orange-400'
                    : 'text-zinc-500 dark:text-zinc-400'
                }`}>
                  if {option.condition.variableName} {option.condition.operator} {String(option.condition.value)}
                </div>
              )}
            </div>
          ))}
        </div>

        <button
          type="button"
          onClick={addOption}
          disabled={data.options.length >= MAX_OPTIONS}
          className="mt-2 flex w-full items-center justify-center gap-1 rounded border border-dashed border-green-400 py-1 text-sm text-green-600 hover:bg-green-100 disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent dark:border-green-500 dark:text-green-400 dark:hover:bg-green-900/30"
          title="Add option"
        >
          + Add Option
        </button>
      </div>

      <input
        type="text"
        value={data.prompt || ''}
        onChange={updatePrompt}
        placeholder="What do you choose?"
        className="mb-3 w-full rounded border border-green-300 bg-white px-2 py-1 text-sm focus:border-green-500 focus:outline-none focus:ring-1 focus:ring-green-500 dark:border-green-600 dark:bg-zinc-800 dark:text-white dark:placeholder-zinc-400"
      />

      <div className="space-y-2">
        {data.options.map((option, index) => (
          <div key={option.id}>
            <div className="relative flex items-center gap-1">
              <input
                type="text"
                value={option.label}
                onChange={(e) => updateOptionLabel(option.id, e.target.value)}
                placeholder={`Option ${index + 1}`}
                className="flex-1 rounded border border-green-300 bg-white px-2 py-1 text-sm focus:border-green-500 focus:outline-none focus:ring-1 focus:ring-green-500 dark:border-green-600 dark:bg-zinc-800 dark:text-white dark:placeholder-zinc-400"
              />
              <button
                type="button"
                onClick={() => setEditingConditionOptionId(option.id)}
                className={`flex h-6 w-6 items-center justify-center rounded text-xs ${
                  option.condition
                    ? 'bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/50 dark:text-amber-300 dark:hover:bg-amber-900/70'
                    : 'text-zinc-400 hover:bg-zinc-100 hover:text-zinc-600 dark:text-zinc-500 dark:hover:bg-zinc-700 dark:hover:text-zinc-300'
                }`}
                title={option.condition ? `Condition: ${option.condition.variableName} ${option.condition.operator} ${option.condition.value}` : 'Add condition'}
              >
                {option.condition ? (
                  <svg xmlns="http://www.w3.org/2000/svg" className="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
                    <path fillRule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clipRule="evenodd" />
                  </svg>
                ) : (
                  <svg xmlns="http://www.w3.org/2000/svg" className="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
                    <path fillRule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clipRule="evenodd" />
                  </svg>
                )}
              </button>
              <button
                type="button"
                onClick={() => removeOption(option.id)}
                disabled={data.options.length <= MIN_OPTIONS}
                className="flex h-6 w-6 items-center justify-center rounded text-red-500 hover:bg-red-100 disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent dark:hover:bg-red-900/30"
                title="Remove option"
              >
                &times;
              </button>
              <Handle
                type="source"
                position={Position.Bottom}
                id={`option-${index}`}
                className="!h-3 !w-3 !border-2 !border-green-500 !bg-white dark:!bg-zinc-800"
                style={{
                  left: `${((index + 1) / (data.options.length + 1)) * 100}%`,
                }}
              />
            </div>
            {option.condition && (
              <div className="ml-1 mt-0.5 flex items-center gap-1">
                <span className="inline-flex items-center rounded-sm bg-amber-100 px-1.5 py-0.5 text-[10px] font-medium text-amber-800 dark:bg-amber-900/40 dark:text-amber-300">
                  if {option.condition.variableName} {option.condition.operator} {option.condition.value}
                </span>
              </div>
            )}
          </div>
        ))}
      </div>

      <button
        type="button"
        onClick={addOption}
        disabled={data.options.length >= MAX_OPTIONS}
        className="mt-2 flex w-full items-center justify-center gap-1 rounded border border-dashed border-green-400 py-1 text-sm text-green-600 hover:bg-green-100 disabled:cursor-not-allowed disabled:opacity-30 disabled:hover:bg-transparent dark:border-green-500 dark:text-green-400 dark:hover:bg-green-900/30"
        title="Add option"
      >
        + Add Option
      </button>

      {editingOption && (
        <OptionConditionEditor
          optionId={editingOption.id}
          optionLabel={editingOption.label}
          condition={editingOption.condition}
          onSave={handleSaveCondition}
          onRemove={handleRemoveCondition}
          onCancel={() => setEditingConditionOptionId(null)}
        />
      )}
    </div>
  )
}
