How can I create a new random shape for a Tetris-like game?

I want to have new tetris pieces to appear in the game the longer you play and it doesn’t work, it makes new shapes but the shapes aren’t centered, they aren’t continuous (like the shape might look like 2 shapes because they aren’t touching), and it sometimes adds a shape that’s already part of the shapes array. Each shape has a max squares of 12 and must fit in a 4×4 space
Here’s my code so far:

function randomShape(score) {
  const maxSize = 12; // Max number of squares per shape
  const centerOffset = 1; // Offset to center the shape
  const maxComplexity = Math.min(Math.floor(score / 100), 6); // Max complexity based on score

  let shape;

  do {
    shape = Array.from({ length: 4 }, () => Array(4).fill(0)); // Create an empty 4x4 shape
    const size = Math.max(1, Math.floor(Math.random() * (maxComplexity + 1))); // Shape size varies based on complexity

    let squaresToPlace = Math.min(size, maxSize); // Limit the squares placed to maxSize

    // Fill the shape with random positions of 1s based on size
    while (squaresToPlace > 0) {
      const x = Math.floor(Math.random() * 4);
      const y = Math.floor(Math.random() * 4);

      // Only place a 1 if the spot is empty
      if (shape[y][x] === 0) {
        shape[y][x] = 1;
        squaresToPlace--;
      }
    }
  } while (!shape.flat(5).includes(1)); // Retry if the shape is empty

  // Centering logic
  const centeredShape = Array.from({ length: 4 }, () => Array(4).fill(0));

  // Get the positions of all filled cells
  const filledPositions = [];
  for (let r = 0; r < 4; r++) {
    for (let c = 0; c < 4; c++) {
      if (shape[r][c] === 1) {
        filledPositions.push({ r, c });
      }
    }
  }

  let amount = 0;
  shape.flat(5).forEach((s) => {
    if (s === 1) amount++;
  });
  if (amount === 1) {
    return [
      [0, 0, 0, 0],
      [0, 0, 0, 0],
      [0, 0, 1, 0],
      [0, 0, 0, 0],
    ];
  }

  // Determine how to center the shape
  const minRow = Math.min(...filledPositions.map((p) => p.r));
  const maxRow = Math.max(...filledPositions.map((p) => p.r));
  const minCol = Math.min(...filledPositions.map((p) => p.c));
  const maxCol = Math.max(...filledPositions.map((p) => p.c));

  // Calculate the offsets needed to center the shape
  const height = maxRow - minRow + 1;
  const width = maxCol - minCol + 1;

  // Calculate vertical and horizontal offsets
  const rowOffset = Math.floor((4 - height) / 2); // Center vertically
  const colOffset = Math.floor((4 - width) / 2); // Center horizontally

  // Place the shape in the centered position
  filledPositions.forEach(({ r, c }) => {
    // Ensure we're placing the piece within bounds
    const newRow = r + rowOffset;
    const newCol = c + colOffset;
    if (newRow >= 0 && newRow < 4 && newCol >= 0 && newCol < 4) {
      centeredShape[newRow][newCol] = 1;
    }
  });

  return centeredShape;
}

I tried to add new random shapes that were supposed to look normal and be centered, but they were broken and uncentered and sometimes dupes.