import { useState, useCallback, useEffect, useRef } from 'react'
import { HelpCircle, Zap, CheckCircle, X, Trash2, Copy, Save } from 'lucide-react'
import { useTreeEditorStore, findNodeInTree } from '@/store/treeEditorStore'
import { NodeFormDecision } from './NodeFormDecision'
import { NodeFormAction } from './NodeFormAction'
import { NodeFormResolution } from './NodeFormResolution'
import { ConfirmDialog } from '@/components/common/ConfirmDialog'
import { cn } from '@/lib/utils'
import type { TreeStructure, NodeType } from '@/types'

interface NodeEditorPanelProps {
  nodeId: string
  onClose: () => void
  onSelectType?: (nodeId: string, type: 'decision' | 'action' | 'solution') => void
}

const TYPE_CONFIG: Record<Exclude<NodeType, 'answer'>, { icon: typeof HelpCircle; label: string; badgeClass: string }> = {
  decision: { icon: HelpCircle, label: 'Decision', badgeClass: 'bg-blue-500/20 text-blue-400' },
  action: { icon: Zap, label: 'Action', badgeClass: 'bg-yellow-500/20 text-yellow-400' },
  solution: { icon: CheckCircle, label: 'Solution', badgeClass: 'bg-green-500/20 text-green-400' },
}

function cloneWithoutChildren(node: TreeStructure): TreeStructure {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const { children: _children, ...rest } = node
  return structuredClone(rest) as TreeStructure
}

export function NodeEditorPanel({ nodeId, onClose, onSelectType }: NodeEditorPanelProps) {
  const treeStructure = useTreeEditorStore(s => s.treeStructure)
  const updateNode = useTreeEditorStore(s => s.updateNode)
  const deleteNode = useTreeEditorStore(s => s.deleteNode)
  const duplicateNode = useTreeEditorStore(s => s.duplicateNode)
  const addNode = useTreeEditorStore(s => s.addNode)
  const selectNode = useTreeEditorStore(s => s.selectNode)

  const node = treeStructure ? findNodeInTree(nodeId, treeStructure) : null
  const [draft, setDraft] = useState<TreeStructure | null>(null)
  const [isDirty, setIsDirty] = useState(false)
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
  const [showDiscardConfirm, setShowDiscardConfirm] = useState(false)
  const panelRef = useRef<HTMLDivElement>(null)

  // Initialize/reset draft when nodeId changes or when node type changes
  // (e.g., answer stub → decision/action/solution via type picker)
  useEffect(() => {
    if (node) {
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setDraft(cloneWithoutChildren(node))
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setIsDirty(false)
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setShowDeleteConfirm(false)
    }
  }, [nodeId, node?.type]) // eslint-disable-line react-hooks/exhaustive-deps

  const handleDraftUpdate = useCallback((updates: Partial<TreeStructure>) => {
    setDraft(prev => prev ? { ...prev, ...updates } : prev)
    setIsDirty(true)
  }, [])

  const handleSave = useCallback(() => {
    if (!draft || !node) return
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { children: _children, ...draftWithoutChildren } = draft
    updateNode(nodeId, draftWithoutChildren)

    // Auto-create answer stubs for new decision options without next_node_id
    if (draft.type === 'decision' && draft.options) {
      const options = draft.options.filter(o => o.label.trim())
      const stubsCreated: Array<{ optId: string; stubId: string }> = []

      options.forEach(opt => {
        if (!opt.next_node_id) {
          const stubId = addNode(nodeId, 'answer')
          updateNode(stubId, { title: opt.label })
          stubsCreated.push({ optId: opt.id, stubId })
        }
      })

      if (stubsCreated.length > 0) {
        const updatedOptions = options.map(o => {
          const stub = stubsCreated.find(s => s.optId === o.id)
          return stub ? { ...o, next_node_id: stub.stubId } : o
        })
        updateNode(nodeId, { options: updatedOptions })
      }
    }

    // Auto-create answer stub for action node without next_node_id
    if (draft.type === 'action' && !draft.next_node_id) {
      const stubId = addNode(nodeId, 'answer')
      updateNode(stubId, { title: 'Next Step' })
      updateNode(nodeId, { next_node_id: stubId })
    }

    setIsDirty(false)
  }, [draft, node, nodeId, updateNode, addNode])

  const handleClose = useCallback(() => {
    if (isDirty) {
      setShowDiscardConfirm(true)
      return
    }
    onClose()
  }, [isDirty, onClose])

  // Escape to close
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        handleClose()
      }
    }
    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [handleClose])

  const handleDelete = useCallback(() => {
    if (!treeStructure) return
    clearInboundReferences(nodeId, treeStructure, updateNode)
    deleteNode(nodeId)
    onClose()
  }, [nodeId, treeStructure, updateNode, deleteNode, onClose])

  const handleDuplicate = useCallback(() => {
    const newId = duplicateNode(nodeId)
    if (newId) {
      selectNode(newId)
    }
  }, [nodeId, duplicateNode, selectNode])

  if (!node || !draft) return null

  // Answer stub: show type picker instead of form
  if (node.type === 'answer') {
    return (
      <div ref={panelRef} className="flex h-full w-[400px] shrink-0 flex-col border-l border-border bg-card">
        <div className="flex items-center justify-between border-b border-border px-4 py-3">
          <span className="text-sm font-heading font-medium text-foreground">
            {node.title || 'Answer Placeholder'}
          </span>
          <button onClick={handleClose} className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground">
            <X className="h-4 w-4" />
          </button>
        </div>
        <div className="flex flex-1 flex-col items-center justify-center gap-4 px-4">
          <p className="text-sm text-muted-foreground text-center">Choose a type for this node:</p>
          <div className="flex gap-2">
            {(['decision', 'action', 'solution'] as const).map(type => {
              const cfg = TYPE_CONFIG[type]
              const TypeIcon = cfg.icon
              return (
                <button
                  key={type}
                  type="button"
                  onClick={() => onSelectType?.(nodeId, type)}
                  className={cn(
                    'flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm font-sans text-xs border transition-colors',
                    type === 'decision' && 'border-blue-500/30 bg-blue-500/10 text-blue-400 hover:bg-blue-500/20',
                    type === 'action' && 'border-yellow-500/30 bg-yellow-500/10 text-yellow-400 hover:bg-yellow-500/20',
                    type === 'solution' && 'border-green-500/30 bg-green-500/10 text-green-400 hover:bg-green-500/20',
                  )}
                >
                  <TypeIcon className="h-4 w-4" /> {cfg.label}
                </button>
              )
            })}
          </div>
        </div>
      </div>
    )
  }

  const config = TYPE_CONFIG[node.type as Exclude<NodeType, 'answer'>] ?? TYPE_CONFIG.decision
  const TypeIcon = config.icon
  const title = node.type === 'decision' ? (node.question || 'Untitled Decision') : (node.title || `Untitled ${config.label}`)
  const isRoot = treeStructure?.id === nodeId

  return (
    <div ref={panelRef} className="flex h-full min-h-0 w-[400px] shrink-0 flex-col border-l border-border bg-card">
      {/* Header */}
      <div className="flex items-center gap-2 border-b border-border px-4 py-3 shrink-0">
        <span className={cn('flex h-5 w-5 shrink-0 items-center justify-center rounded', config.badgeClass)}>
          <TypeIcon className="h-3 w-3" />
        </span>
        <span className="flex-1 truncate text-sm font-heading font-medium text-foreground">{title}</span>
        <button onClick={handleClose} className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground">
          <X className="h-4 w-4" />
        </button>
      </div>

      {/* Body — scrollable form area */}
      <div className="min-h-0 flex-1 overflow-y-auto px-4 py-3 scroll-pb-24">
        {draft.type === 'decision' && <NodeFormDecision node={draft} onUpdate={handleDraftUpdate} />}
        {draft.type === 'action' && <NodeFormAction node={draft} onUpdate={handleDraftUpdate} />}
        {draft.type === 'solution' && <NodeFormResolution node={draft} onUpdate={handleDraftUpdate} />}
      </div>

      {/* Footer */}
      <div className="sticky bottom-0 flex items-center gap-2 border-t border-border bg-card px-4 py-3 shrink-0">
        <button
          onClick={handleSave}
          disabled={!isDirty}
          className={cn(
            'flex items-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium text-white transition-opacity',
            isDirty ? 'bg-primary hover:brightness-110' : 'bg-primary opacity-50 cursor-not-allowed'
          )}
        >
          <Save className="h-3.5 w-3.5" /> Save
        </button>
        <button
          onClick={handleClose}
          className="rounded-lg border border-border px-4 py-2 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
        >
          Cancel
        </button>
        <div className="flex-1" />
        {!isRoot && (
          <>
            <button
              onClick={handleDuplicate}
              className="rounded-md p-2 text-muted-foreground hover:bg-accent hover:text-foreground"
              title="Duplicate"
            >
              <Copy className="h-4 w-4" />
            </button>
            {showDeleteConfirm ? (
              <div className="flex items-center gap-1">
                <button
                  onClick={handleDelete}
                  className="rounded-md bg-red-500/20 px-2 py-1 text-xs text-red-400 hover:bg-red-500/30"
                >
                  Confirm
                </button>
                <button
                  onClick={() => setShowDeleteConfirm(false)}
                  className="rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent"
                >
                  Cancel
                </button>
              </div>
            ) : (
              <button
                onClick={() => setShowDeleteConfirm(true)}
                className="rounded-md p-2 text-muted-foreground hover:bg-accent hover:text-red-400"
                title="Delete"
              >
                <Trash2 className="h-4 w-4" />
              </button>
            )}
          </>
        )}
      </div>

      <ConfirmDialog
        isOpen={showDiscardConfirm}
        onClose={() => setShowDiscardConfirm(false)}
        onConfirm={() => {
          setShowDiscardConfirm(false)
          onClose()
        }}
        title="Discard Changes"
        message="You have unsaved changes. Discard them?"
        confirmLabel="Discard"
      />
    </div>
  )
}

// Clear all next_node_id references to a node before deleting
function clearInboundReferences(
  nodeId: string,
  treeStructure: TreeStructure,
  updateNode: (id: string, updates: Partial<TreeStructure>) => void
) {
  function walk(node: TreeStructure) {
    if (node.type === 'decision' && node.options) {
      const needsUpdate = node.options.some(o => o.next_node_id === nodeId)
      if (needsUpdate) {
        updateNode(node.id, {
          options: node.options.map(o => o.next_node_id === nodeId ? { ...o, next_node_id: '' } : o),
        })
      }
    }
    if (node.type === 'action' && node.next_node_id === nodeId) {
      updateNode(node.id, { next_node_id: '' })
    }
    node.children?.forEach(walk)
  }
  walk(treeStructure)
}
