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

/**
 * Number of Islands (LeetCode 200)
 *
 * Grid:
 *   ["1","1","0","0","0"]
 *   ["1","1","0","0","0"]
 *   ["0","0","1","0","0"]
 *   ["0","0","0","1","1"]
 *
 * Output: 3 islands
 *   Island 1: (0,0), (0,1), (1,0), (1,1)
 *   Island 2: (2,2)
 *   Island 3: (3,3), (3,4)
 */

// Grid data (4 rows x 5 cols)
const GRID = [
  ['1', '1', '0', '0', '0'],
  ['1', '1', '0', '0', '0'],
  ['0', '0', '1', '0', '0'],
  ['0', '0', '0', '1', '1'],
];

// Helper to create grid state with cell highlighting
function createIslandGrid(
  visitedCells: Set<string>,
  currentCell?: string,
  exploringCells?: Set<string>,
  label = 'Island Grid'
) {
  const cells: GridCellState[][] = GRID.map((row, r) =>
    row.map((val, c) => {
      const key = `${r}-${c}`;
      let state: GridCellState['state'] = val === '0' ? 'dimmed' : 'normal';
      if (visitedCells.has(key)) state = 'success';
      if (exploringCells?.has(key)) state = 'computing';
      if (key === currentCell) state = 'highlighted';
      return { id: `cell-${r}-${c}`, value: val, row: r, col: c, state };
    })
  );

  return {
    id: 'island-grid',
    cells,
    rowLabels: [0, 1, 2, 3],
    colLabels: [0, 1, 2, 3, 4],
    label,
  };
}

// Helper to create initial grid showing all land/water
function createInitialGrid() {
  const cells: GridCellState[][] = GRID.map((row, r) =>
    row.map((val, c) => ({
      id: `cell-${r}-${c}`,
      value: val,
      row: r,
      col: c,
      state: val === '0' ? 'dimmed' : 'normal',
    }))
  );

  return {
    id: 'island-grid',
    cells,
    rowLabels: [0, 1, 2, 3],
    colLabels: [0, 1, 2, 3, 4],
    label: 'Island Grid',
  };
}

export const numberOfIslandsAlgorithm: AlgorithmDefinition = {
  id: 'number-of-islands',
  title: 'Number of Islands - Matrix Traversal',
  slug: 'number-of-islands',
  pattern: {
    name: 'Matrix Traversal',
    description:
      'Explore a 2D grid using DFS or BFS to find connected components, paths, or regions.',
  },
  problemStatement:
    'Given a 2D grid of \'1\'s (land) and \'0\'s (water), count the number of islands. An island is surrounded by water and formed by connecting adjacent lands horizontally or vertically.',
  intuition:
    'Think of the grid as a map. Each unvisited land cell could be the start of a new island. Use DFS to explore all connected land cells from a starting point, marking them visited. Each time we start a new DFS from an unvisited land cell, we\'ve found a new island.',
  code: {
    language: 'python',
    code: `def numIslands(grid: list[list[str]]) -> int:
    if not grid:
        return 0

    rows, cols = len(grid), len(grid[0])
    count = 0

    def dfs(r: int, c: int):
        if r < 0 or r >= rows or c < 0 or c >= cols:
            return
        if grid[r][c] == '0':
            return
        grid[r][c] = '0'  # Mark visited
        dfs(r + 1, c)  # Down
        dfs(r - 1, c)  # Up
        dfs(r, c + 1)  # Right
        dfs(r, c - 1)  # Left

    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == '1':
                count += 1
                dfs(r, c)

    return count`,
  },
  initialExample: {
    input: {
      grid: [
        ['1', '1', '0', '0', '0'],
        ['1', '1', '0', '0', '0'],
        ['0', '0', '1', '0', '0'],
        ['0', '0', '0', '1', '1'],
      ],
    },
    expected: 3,
  },
  steps: [
    // ==========================================
    // Phase 1: Problem (2 steps)
    // ==========================================
    {
      id: 'problem-1',
      phase: 'problem',
      explanation:
        'We have a 4x5 grid where \'1\' represents land and \'0\' represents water. Our goal is to count distinct islands (connected land regions).',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [],
        calculations: [],
        grids: [createInitialGrid()],
      },
    },
    {
      id: 'problem-2',
      phase: 'problem',
      explanation:
        'Land cells are connected horizontally or vertically (not diagonally). Looking at this grid, we can visually spot 3 separate islands.',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'islands', name: 'Expected', value: '3 islands' },
        ],
        calculations: [],
        grids: [createInitialGrid()],
      },
    },

    // ==========================================
    // Phase 2: Intuition (3 steps)
    // ==========================================
    {
      id: 'intuition-1',
      phase: 'intuition',
      explanation:
        'Strategy: Scan the grid cell by cell. When we find an unvisited land cell (\'1\'), we\'ve discovered a new island. Increment count and explore all connected land using DFS.',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'islandCount', value: 0 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(), '0-0')],
      },
    },
    {
      id: 'intuition-2',
      phase: 'intuition',
      explanation:
        'DFS explores in 4 directions (up, down, left, right). As we visit each land cell, we mark it as visited by changing \'1\' to \'0\'. This prevents counting the same island twice.',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'islandCount', value: 1 },
        ],
        calculations: [
          { id: 'calc-1', expression: 'DFS: (0,0) → neighbors', result: '4 directions', position: 'above' },
        ],
        grids: [createIslandGrid(new Set(), '0-0', new Set(['0-1', '1-0']))],
      },
    },
    {
      id: 'intuition-3',
      phase: 'intuition',
      explanation:
        'Key insight: Each time we start DFS from a new unvisited \'1\', we\'ve found a complete new island. The DFS call explores the entire island before returning.',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'islandCount', value: 1 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1']))],
      },
    },

    // ==========================================
    // Phase 3: Pattern (2 steps)
    // ==========================================
    {
      id: 'pattern-1',
      phase: 'pattern',
      explanation:
        'Matrix Traversal pattern: Treat the grid as an implicit graph where each cell is a node, and adjacent cells are edges. DFS/BFS finds connected components.',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'pattern', name: 'Pattern', value: 'Connected Components' },
        ],
        calculations: [],
        grids: [createInitialGrid()],
      },
    },
    {
      id: 'pattern-2',
      phase: 'pattern',
      explanation:
        'Time: O(rows × cols) - we visit each cell at most once. Space: O(rows × cols) in worst case for DFS recursion stack (all land).',
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'time', name: 'Time', value: 'O(m × n)' },
          { id: 'space', name: 'Space', value: 'O(m × n)' },
        ],
        calculations: [],
        grids: [createInitialGrid()],
      },
    },

    // ==========================================
    // Phase 4: Code (4 steps)
    // ==========================================
    {
      id: 'code-1',
      phase: 'code',
      explanation:
        'Initialize: Get grid dimensions, set island count to 0. We\'ll modify the grid in-place to track visited cells.',
      codeLine: 5,
      codeHighlightLines: [2, 3, 4, 5, 6],
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'rows', name: 'rows', value: 4 },
          { id: 'cols', name: 'cols', value: 5 },
          { id: 'count', name: 'count', value: 0 },
        ],
        calculations: [],
        grids: [createInitialGrid()],
      },
    },
    {
      id: 'code-2',
      phase: 'code',
      explanation:
        'DFS function: Base cases return early if out of bounds or cell is water. Otherwise, mark cell visited and recurse in all 4 directions.',
      codeLine: 12,
      codeHighlightLines: [8, 9, 10, 11, 12, 13, 14, 15, 16, 17],
      dataState: {
        arrays: [],
        pointers: [],
        variables: [],
        calculations: [
          { id: 'calc-1', expression: 'dfs(r, c)', result: 'explore & mark', position: 'above' },
        ],
        grids: [createInitialGrid()],
      },
    },
    {
      id: 'code-3',
      phase: 'code',
      explanation:
        'Main loop: Scan every cell. When we find \'1\' (unvisited land), increment count and run DFS to mark entire island as visited.',
      codeLine: 22,
      codeHighlightLines: [19, 20, 21, 22, 23],
      dataState: {
        arrays: [],
        pointers: [],
        variables: [],
        calculations: [],
        grids: [createIslandGrid(new Set(), '0-0')],
      },
    },
    {
      id: 'code-4',
      phase: 'code',
      explanation:
        'Return the final count. Each DFS call discovers one complete island, so count equals the number of islands.',
      codeLine: 25,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: '?' },
        ],
        calculations: [],
        grids: [createInitialGrid()],
      },
    },

    // ==========================================
    // Phase 5: Execution (~12 steps)
    // ==========================================
    {
      id: 'exec-1',
      phase: 'execution',
      explanation:
        'Start scanning at (0,0). Found \'1\' - this is unvisited land! Increment count to 1 and start DFS to explore this island.',
      codeLine: 21,
      decision: {
        question: 'Is cell (0,0) land?',
        answer: 'Yes, grid[0][0] = \'1\'',
        action: 'New island found! count++, start DFS',
      },
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'r', name: 'r', value: 0 },
          { id: 'c', name: 'c', value: 0 },
          { id: 'count', name: 'count', value: 1 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(), '0-0')],
        gridPointers: [
          { id: 'ptr-curr', name: 'current', row: 0, col: 0, color: 'current' },
        ],
      },
    },
    {
      id: 'exec-2',
      phase: 'execution',
      explanation:
        'DFS from (0,0): Mark as visited, explore neighbors. Cell (0,1) is land - recurse there. Cell (1,0) is also land.',
      codeLine: 13,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: 1 },
        ],
        calculations: [
          { id: 'calc-1', expression: 'dfs(0,0) → dfs(0,1), dfs(1,0)', result: 'exploring', position: 'above' },
        ],
        grids: [createIslandGrid(new Set(['0-0']), undefined, new Set(['0-1', '1-0']))],
        gridPointers: [
          { id: 'ptr-curr', name: 'visited', row: 0, col: 0, color: 'result' },
        ],
      },
    },
    {
      id: 'exec-3',
      phase: 'execution',
      explanation:
        'DFS explores (0,1), then (1,0), then (1,1). All 4 cells of island 1 are now marked as visited (green).',
      codeLine: 13,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: 1 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1']))],
      },
    },
    {
      id: 'exec-4',
      phase: 'execution',
      explanation:
        'DFS complete for island 1. Continue scanning: (0,2), (0,3), (0,4) are all water (\'0\'). Skip them.',
      codeLine: 20,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'r', name: 'r', value: 0 },
          { id: 'c', name: 'c', value: 2 },
          { id: 'count', name: 'count', value: 1 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1']), '0-2')],
        gridPointers: [
          { id: 'ptr-scan', name: 'scan', row: 0, col: 2, color: 'current' },
        ],
      },
    },
    {
      id: 'exec-5',
      phase: 'execution',
      explanation:
        'Scanning row 1: (1,0) and (1,1) already visited. (1,2), (1,3), (1,4) are water. Continue to row 2.',
      codeLine: 20,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'r', name: 'r', value: 1 },
          { id: 'count', name: 'count', value: 1 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1']))],
      },
    },
    {
      id: 'exec-6',
      phase: 'execution',
      explanation:
        'Scan (2,0), (2,1) - water. At (2,2): Found \'1\'! This is a new unvisited land cell. Increment count to 2.',
      codeLine: 21,
      decision: {
        question: 'Is cell (2,2) land?',
        answer: 'Yes, grid[2][2] = \'1\'',
        action: 'New island found! count++',
      },
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'r', name: 'r', value: 2 },
          { id: 'c', name: 'c', value: 2 },
          { id: 'count', name: 'count', value: 2 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1']), '2-2')],
        gridPointers: [
          { id: 'ptr-curr', name: 'current', row: 2, col: 2, color: 'current' },
        ],
      },
    },
    {
      id: 'exec-7',
      phase: 'execution',
      explanation:
        'DFS from (2,2): Check all 4 neighbors - all are water or out of bounds. This is a single-cell island. Mark visited.',
      codeLine: 13,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: 2 },
        ],
        calculations: [
          { id: 'calc-1', expression: 'dfs(2,2) neighbors', result: 'all water', position: 'above' },
        ],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1', '2-2']))],
      },
    },
    {
      id: 'exec-8',
      phase: 'execution',
      explanation:
        'Continue scanning row 2 and row 3: (2,3), (2,4), (3,0), (3,1), (3,2) are all water. Skip them.',
      codeLine: 20,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'r', name: 'r', value: 3 },
          { id: 'c', name: 'c', value: 2 },
          { id: 'count', name: 'count', value: 2 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1', '2-2']), '3-2')],
        gridPointers: [
          { id: 'ptr-scan', name: 'scan', row: 3, col: 2, color: 'current' },
        ],
      },
    },
    {
      id: 'exec-9',
      phase: 'execution',
      explanation:
        'At (3,3): Found \'1\'! This is another new island. Increment count to 3 and start DFS.',
      codeLine: 21,
      decision: {
        question: 'Is cell (3,3) land?',
        answer: 'Yes, grid[3][3] = \'1\'',
        action: 'New island found! count++',
      },
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'r', name: 'r', value: 3 },
          { id: 'c', name: 'c', value: 3 },
          { id: 'count', name: 'count', value: 3 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1', '2-2']), '3-3')],
        gridPointers: [
          { id: 'ptr-curr', name: 'current', row: 3, col: 3, color: 'current' },
        ],
      },
    },
    {
      id: 'exec-10',
      phase: 'execution',
      explanation:
        'DFS from (3,3): Mark visited, explore neighbors. Found (3,4) is also land! Recurse to explore it.',
      codeLine: 13,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: 3 },
        ],
        calculations: [
          { id: 'calc-1', expression: 'dfs(3,3) → dfs(3,4)', result: 'found neighbor', position: 'above' },
        ],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1', '2-2', '3-3']), undefined, new Set(['3-4']))],
        gridPointers: [
          { id: 'ptr-curr', name: 'exploring', row: 3, col: 4, color: 'current' },
        ],
      },
    },
    {
      id: 'exec-11',
      phase: 'execution',
      explanation:
        'DFS visits (3,4): Mark visited. No more land neighbors. Island 3 complete with cells (3,3) and (3,4).',
      codeLine: 13,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: 3 },
        ],
        calculations: [],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1', '2-2', '3-3', '3-4']))],
      },
    },
    {
      id: 'exec-12',
      phase: 'execution',
      explanation:
        'Scan complete! All cells visited. We found 3 islands: (1) 4 cells top-left, (2) 1 cell middle, (3) 2 cells bottom-right.',
      codeLine: 25,
      dataState: {
        arrays: [],
        pointers: [],
        variables: [
          { id: 'count', name: 'count', value: 3, derivation: '3 connected components' },
        ],
        calculations: [
          { id: 'calc-1', expression: 'return count', result: '3', position: 'above' },
        ],
        grids: [createIslandGrid(new Set(['0-0', '0-1', '1-0', '1-1', '2-2', '3-3', '3-4']), undefined, undefined, 'Result: 3 Islands')],
      },
    },
  ],
};
