// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package google.registry.tools;

import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.util.DateTimeUtils.END_INSTANT;
import static google.registry.util.DateTimeUtils.START_INSTANT;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import google.registry.model.EppResource;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntryDao;
import google.registry.persistence.VKey;
import google.registry.tools.CommandUtilities.ResourceType;
import google.registry.tools.params.InstantParameter;
import google.registry.util.Clock;
import google.registry.xml.XmlTransformer;
import jakarta.inject.Inject;
import java.time.Instant;

/** Command to show history entries. */
@Parameters(
    separators = " =",
    commandDescription = "Show history entries that occurred in a given time range")
final class GetHistoryEntriesCommand implements Command {

  @Inject Clock clock;

  @Parameter(
      names = {"-a", "--after"},
      description = "Only show history entries that occurred at or after this time",
      converter = InstantParameter.class)
  private Instant after = START_INSTANT;

  @Parameter(
      names = {"-b", "--before"},
      description = "Only show history entries that occurred at or before this time",
      converter = InstantParameter.class)
  private Instant before = END_INSTANT;

  @Parameter(names = "--type", description = "Resource type.")
  private ResourceType type;

  @Parameter(names = "--id", description = "Foreign key of the resource.")
  private String uniqueId;

  @Override
  public void run() {
    Iterable<? extends HistoryEntry> historyEntries;
    if (type != null || uniqueId != null) {
      checkArgument(
          type != null && uniqueId != null,
          "If either of 'type' or 'id' are set then both must be");
      VKey<? extends EppResource> parentKey = type.getKey(uniqueId, clock.now());
      historyEntries = HistoryEntryDao.loadHistoryObjectsForResource(parentKey, after, before);
    } else {
      historyEntries = HistoryEntryDao.loadAllHistoryObjects(after, before);
    }
    for (HistoryEntry entry : historyEntries) {
      System.out.printf(
          "Client: %s\nTime: %s\nClient TRID: %s\nServer TRID: %s\n%s\n",
          entry.getRegistrarId(),
          entry.getModificationTime(),
          entry.getTrid() == null ? null : entry.getTrid().getClientTransactionId().orElse(null),
          entry.getTrid() == null ? null : entry.getTrid().getServerTransactionId(),
          entry.getXmlBytes() == null
              ? String.format("[no XML stored for %s]\n", entry.getType())
              : XmlTransformer.prettyPrint(entry.getXmlBytes()));
    }
  }
}
