import type { AlgorithmDefinition } from '@/lib/visualizations/types';

/**
 * Tree structure (level order: [4, 2, 6, 1, 3, 5, 7]):
 *
 *          4 (root)
 *        /   \
 *       2     6
 *      / \   / \
 *     1   3 5   7
 *
 * Inorder traversal output: [1, 2, 3, 4, 5, 6, 7]
 */

// Node IDs for our tree
const NODE_4 = 'n4';
const NODE_2 = 'n2';
const NODE_6 = 'n6';
const NODE_1 = 'n1';
const NODE_3 = 'n3';
const NODE_5 = 'n5';
const NODE_7 = 'n7';

// Helper to create tree state with specific node states
function createTreeState(nodeStates: Record<string, 'normal' | 'current' | 'visiting' | 'visited' | 'highlighted'>) {
  return {
    id: 'tree',
    label: 'Binary Search Tree',
    rootId: NODE_4,
    nodes: [
      { id: NODE_4, value: 4, state: nodeStates[NODE_4] ?? 'normal', left: NODE_2, right: NODE_6 },
      { id: NODE_2, value: 2, state: nodeStates[NODE_2] ?? 'normal', left: NODE_1, right: NODE_3 },
      { id: NODE_6, value: 6, state: nodeStates[NODE_6] ?? 'normal', left: NODE_5, right: NODE_7 },
      { id: NODE_1, value: 1, state: nodeStates[NODE_1] ?? 'normal', left: null, right: null },
      { id: NODE_3, value: 3, state: nodeStates[NODE_3] ?? 'normal', left: null, right: null },
      { id: NODE_5, value: 5, state: nodeStates[NODE_5] ?? 'normal', left: null, right: null },
      { id: NODE_7, value: 7, state: nodeStates[NODE_7] ?? 'normal', left: null, right: null },
    ],
  };
}

// Helper to create stack state
function createStackState(values: number[], highlightTop = false) {
  return {
    id: 'traversal-stack',
    label: 'Traversal Stack',
    elements: values.map((v, i) => ({
      id: `stack-${i}`,
      value: v,
      state: (highlightTop && i === values.length - 1 ? 'highlighted' : 'normal') as 'normal' | 'highlighted',
    })),
  };
}

// Helper to create output array state
function createOutputState(values: (number | null)[], highlightIndex?: number) {
  const maxLen = 7;
  const elements = [];
  for (let i = 0; i < maxLen; i++) {
    const val = values[i];
    elements.push({
      value: val ?? 0,
      index: i,
      state: (val === null ? 'dimmed' : i === highlightIndex ? 'highlighted' : 'success') as 'normal' | 'highlighted' | 'dimmed' | 'success' | 'comparing',
    });
  }
  return {
    id: 'output',
    label: 'Output Array',
    elements,
  };
}

export const treeTraversalAlgorithm: AlgorithmDefinition = {
  id: 'tree-traversal',
  title: 'Inorder Tree Traversal (Iterative)',
  slug: 'tree-traversal',
  pattern: {
    name: 'Tree Traversal',
    description:
      'Use a stack to simulate recursion and traverse a binary tree in inorder (Left-Root-Right) order.',
  },
  problemStatement:
    'Given a binary search tree, traverse it in inorder (Left-Root-Right) to produce a sorted output. Use an iterative approach with an explicit stack.',
  intuition:
    'Recursion implicitly uses a call stack. We can make this explicit: go left as far as possible while pushing nodes, then pop to process and move right. For a BST, this produces sorted order.',
  code: {
    language: 'python',
    code: `def inorder_traversal(root):
    result = []
    stack = []
    curr = root

    while curr or stack:
        # Go left as far as possible
        while curr:
            stack.append(curr)
            curr = curr.left

        # Pop and process
        curr = stack.pop()
        result.append(curr.val)

        # Move to right subtree
        curr = curr.right

    return result`,
  },
  initialExample: {
    input: { tree: [4, 2, 6, 1, 3, 5, 7] },
    expected: [1, 2, 3, 4, 5, 6, 7],
  },
  steps: [
    // ==========================================
    // Phase 1: Problem (2 steps)
    // ==========================================
    {
      id: 'problem-1',
      phase: 'problem',
      explanation:
        'We have a binary search tree. Our goal is to visit all nodes in inorder (Left-Root-Right), which for a BST gives us sorted output.',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({})],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'problem-2',
      phase: 'problem',
      explanation:
        'For this BST: visit left subtree (1, 2, 3), then root (4), then right subtree (5, 6, 7). Expected output: [1, 2, 3, 4, 5, 6, 7].',
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'highlighted' })],
        stacks: [createStackState([])],
      },
    },

    // ==========================================
    // Phase 2: Intuition (3 steps)
    // ==========================================
    {
      id: 'intuition-1',
      phase: 'intuition',
      explanation:
        'Recursion uses an implicit call stack. We can make this explicit: maintain our own stack to track nodes waiting to be processed.',
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({})],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'intuition-2',
      phase: 'intuition',
      explanation:
        'Pattern: Starting from any node, go left as far as possible, pushing each node to the stack. When you can\'t go left, pop and process, then move right.',
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'current', [NODE_2]: 'visiting', [NODE_1]: 'visiting' })],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'intuition-3',
      phase: 'intuition',
      explanation:
        'The stack remembers ancestors waiting for their right subtrees to be processed. This mimics how recursion unwinds.',
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visiting', [NODE_1]: 'current' })],
        stacks: [createStackState([4, 2], true)],
      },
    },

    // ==========================================
    // Phase 3: Pattern (2 steps)
    // ==========================================
    {
      id: 'pattern-1',
      phase: 'pattern',
      explanation:
        'The iterative pattern has three repeating phases: (1) Go left and push, (2) Pop and process, (3) Move right.',
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({})],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'pattern-2',
      phase: 'pattern',
      explanation:
        'We continue while either curr points to a node OR the stack is non-empty. Both conditions must be false to terminate.',
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'node' },
          { id: 'stack', name: 'stack', value: '[]' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'current' })],
        stacks: [createStackState([])],
      },
    },

    // ==========================================
    // Phase 4: Code (3 steps)
    // ==========================================
    {
      id: 'code-1',
      phase: 'code',
      explanation:
        'Initialize: empty result array, empty stack, and curr pointing to root.',
      codeLine: 2,
      codeHighlightLines: [2, 3, 4],
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'root (4)' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'current' })],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'code-2',
      phase: 'code',
      explanation:
        'Inner while loop: Go left as far as possible, pushing each node. This processes the left subtree first.',
      codeLine: 8,
      codeHighlightLines: [8, 9, 10],
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visiting', [NODE_1]: 'current' })],
        stacks: [createStackState([4, 2])],
      },
    },
    {
      id: 'code-3',
      phase: 'code',
      explanation:
        'After going left, pop from stack, add value to result, then move to right child.',
      codeLine: 13,
      codeHighlightLines: [13, 14, 17],
      dataState: {
        arrays: [createOutputState([1, null, null, null, null, null], 0)],
        pointers: [],
        variables: [],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'current', [NODE_1]: 'visited' })],
        stacks: [createStackState([4])],
      },
    },

    // ==========================================
    // Phase 5: Execution (14 steps)
    // ==========================================
    {
      id: 'exec-1',
      phase: 'execution',
      explanation:
        'Start: curr = 4 (root), stack = []. The outer loop condition "curr or stack" is true.',
      codeLine: 6,
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 4 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'current' })],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'exec-2',
      phase: 'execution',
      explanation:
        'Go left: Push 4 to stack, move curr to left child (2). Stack: [4]',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 2, previousValue: 4 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'current' })],
        stacks: [createStackState([4], true)],
      },
    },
    {
      id: 'exec-3',
      phase: 'execution',
      explanation:
        'Continue left: Push 2 to stack, move curr to left child (1). Stack: [4, 2]',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 1, previousValue: 2 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visiting', [NODE_1]: 'current' })],
        stacks: [createStackState([4, 2], true)],
      },
    },
    {
      id: 'exec-4',
      phase: 'execution',
      explanation:
        'Push 1 to stack, move curr to left child (null). Stack: [4, 2, 1]. Can\'t go left anymore.',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([null, null, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null', previousValue: 1 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visiting', [NODE_1]: 'visiting' })],
        stacks: [createStackState([4, 2, 1], true)],
      },
    },
    {
      id: 'exec-5',
      phase: 'execution',
      explanation:
        'Pop 1 from stack, add to result. Output: [1]. Move to right child of 1 (null).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, null, null, null, null, null, null], 0)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visiting', [NODE_1]: 'visited' })],
        stacks: [createStackState([4, 2])],
      },
    },
    {
      id: 'exec-6',
      phase: 'execution',
      explanation:
        'curr is null but stack is non-empty. Pop 2 from stack, add to result. Output: [1, 2]. Move to right child (3).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, 2, null, null, null, null, null], 1)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 3, previousValue: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'current' })],
        stacks: [createStackState([4])],
      },
    },
    {
      id: 'exec-7',
      phase: 'execution',
      explanation:
        'At node 3. Go left: Push 3 to stack, move to left child (null). Stack: [4, 3]',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([1, 2, null, null, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null', previousValue: 3 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visiting' })],
        stacks: [createStackState([4, 3], true)],
      },
    },
    {
      id: 'exec-8',
      phase: 'execution',
      explanation:
        'Pop 3 from stack, add to result. Output: [1, 2, 3]. Move to right child (null).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, 2, 3, null, null, null, null], 2)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visiting', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited' })],
        stacks: [createStackState([4])],
      },
    },
    {
      id: 'exec-9',
      phase: 'execution',
      explanation:
        'Pop 4 from stack (the root!), add to result. Output: [1, 2, 3, 4]. Move to right child (6).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, null, null, null], 3)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 6, previousValue: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'current' })],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'exec-10',
      phase: 'execution',
      explanation:
        'At node 6. Go left: Push 6 to stack, move to left child (5). Stack: [6]',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 5, previousValue: 6 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visiting', [NODE_5]: 'current' })],
        stacks: [createStackState([6], true)],
      },
    },
    {
      id: 'exec-11',
      phase: 'execution',
      explanation:
        'At node 5. Go left: Push 5 to stack, move to left child (null). Stack: [6, 5]',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, null, null, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null', previousValue: 5 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visiting', [NODE_5]: 'visiting' })],
        stacks: [createStackState([6, 5], true)],
      },
    },
    {
      id: 'exec-12',
      phase: 'execution',
      explanation:
        'Pop 5 from stack, add to result. Output: [1, 2, 3, 4, 5]. Move to right child (null).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, 5, null, null], 4)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visiting', [NODE_5]: 'visited' })],
        stacks: [createStackState([6])],
      },
    },
    {
      id: 'exec-13',
      phase: 'execution',
      explanation:
        'Pop 6 from stack, add to result. Output: [1, 2, 3, 4, 5, 6]. Move to right child (7).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, 5, 6, null], 5)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 7, previousValue: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visited', [NODE_5]: 'visited', [NODE_7]: 'current' })],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'exec-14',
      phase: 'execution',
      explanation:
        'At node 7. Go left: Push 7 to stack, move to left child (null). Stack: [7]',
      codeLine: 9,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, 5, 6, null])],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null', previousValue: 7 },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visited', [NODE_5]: 'visited', [NODE_7]: 'visiting' })],
        stacks: [createStackState([7], true)],
      },
    },
    {
      id: 'exec-15',
      phase: 'execution',
      explanation:
        'Pop 7 from stack, add to result. Output: [1, 2, 3, 4, 5, 6, 7]. Move to right child (null).',
      codeLine: 14,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, 5, 6, 7], 6)],
        pointers: [],
        variables: [
          { id: 'curr', name: 'curr', value: 'null' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visited', [NODE_5]: 'visited', [NODE_7]: 'visited' })],
        stacks: [createStackState([])],
      },
    },
    {
      id: 'exec-16',
      phase: 'execution',
      explanation:
        'Done! curr is null AND stack is empty. Final output: [1, 2, 3, 4, 5, 6, 7] - the BST values in sorted order.',
      codeLine: 19,
      dataState: {
        arrays: [createOutputState([1, 2, 3, 4, 5, 6, 7])],
        pointers: [],
        variables: [
          { id: 'result', name: 'result', value: '[1, 2, 3, 4, 5, 6, 7]' },
        ],
        calculations: [],
        trees: [createTreeState({ [NODE_4]: 'visited', [NODE_2]: 'visited', [NODE_1]: 'visited', [NODE_3]: 'visited', [NODE_6]: 'visited', [NODE_5]: 'visited', [NODE_7]: 'visited' })],
        stacks: [createStackState([])],
      },
    },
  ],
};
