@ShellMethod(key = "show restore", value = "Show details of a restore instant")
  public String showRestore(
          @ShellOption(value = {"--instant"}, help = "Restore instant") String restoreInstant,
          @ShellOption(value = {"--limit"}, help = "Limit #rows to be displayed", defaultValue = "10") Integer limit,
          @ShellOption(value = {"--sortBy"}, help = "Sorting Field", defaultValue = "") final String sortByField,
          @ShellOption(value = {"--desc"}, help = "Ordering", defaultValue = "false") final boolean descending,
          @ShellOption(value = {"--headeronly"}, help = "Print Header Only",
                  defaultValue = "false") final boolean headerOnly) {

    HoodieActiveTimeline activeTimeline = HoodieCLI.getTableMetaClient().getActiveTimeline();
    List<HoodieInstant> matchingInstants = activeTimeline.filterCompletedInstants().filter(completed ->
            completed.getTimestamp().equals(restoreInstant)).getInstants();
    if (matchingInstants.isEmpty()) {
      matchingInstants = activeTimeline.filterInflights().filter(inflight ->
              inflight.getTimestamp().equals(restoreInstant)).getInstants();
    }

    // Assuming a single exact match is found in either completed or inflight instants
    HoodieInstant instant = matchingInstants.get(0);
    List<Comparable[]> outputRows = new ArrayList<>();
    populateOutputFromRestoreInstant(instant, outputRows, activeTimeline);

    TableHeader header = createResultHeader();
    return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, outputRows);
  }
@Test
  public void testShowRestore() throws IOException {
    // get instant
    HoodieActiveTimeline activeTimeline = HoodieCLI.getTableMetaClient().getActiveTimeline();
    Stream<HoodieInstant> restores = activeTimeline.getRestoreTimeline().filterCompletedInstants().getInstantsAsStream();
    HoodieInstant instant = restores.findFirst().orElse(null);
    assertNotNull(instant, "The instant can not be null.");

    Object result = shell.evaluate(() -> "show restore --instant " + instant.getTimestamp());
    assertTrue(ShellEvaluationResultUtil.isSuccess(result));

    // get metadata of instant
    HoodieRestoreMetadata instantMetadata = TimelineMetadataUtils.deserializeAvroMetadata(
            activeTimeline.getInstantDetails(instant).get(), HoodieRestoreMetadata.class);

    // generate expected result
    TableHeader header = new TableHeader()
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT)
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_RESTORE_INSTANT)
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_TIME_TOKEN_MILLIS)
            .addTableHeaderField(HoodieTableHeaderFields.HEADER_RESTORE_STATE);

    List<Comparable[]> rows = new ArrayList<>();
    instantMetadata.getInstantsToRollback().forEach((String rolledbackInstant) -> {
      Comparable[] row = new Comparable[4];
      row[0] = instantMetadata.getStartRestoreTime();
      row[1] = rolledbackInstant;
      row[2] = instantMetadata.getTimeTakenInMillis();
      row[3] = HoodieInstant.State.COMPLETED.toString();
      rows.add(row);
    });
    String expected = HoodiePrintHelper.print(header, new HashMap<>(), "", false, -1,
            false, rows);
    expected = removeNonWordAndStripSpace(expected);
    String got = removeNonWordAndStripSpace(result.toString());
    assertEquals(expected, got);
  }