// 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.model.domain;

import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static org.junit.jupiter.api.Assertions.assertThrows;

import google.registry.flows.domain.DomainFlowUtils.RegistrantProhibitedException;
import google.registry.flows.exceptions.ContactsProhibitedException;
import google.registry.model.ResourceCommandTestCase;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.EppInput.ResourceCommandWrapper;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.testing.EppLoader;
import org.junit.jupiter.api.Test;

/** Tests for DomainCommand. */
class DomainCommandTest extends ResourceCommandTestCase {

  @Test
  void testCreate() throws Exception {
    // This EPP command wouldn't be allowed for policy reasons, but should marshal/unmarshal fine.
    doXmlRoundtripTest("domain_create.xml");
  }

  @Test
  void testCreate_sunriseSignedMark() throws Exception {
    doXmlRoundtripTest("domain_create_sunrise_signed_mark.xml");
  }

  @Test
  void testCreate_sunriseCode() throws Exception {
    doXmlRoundtripTest("domain_create_sunrise_code.xml");
  }

  @Test
  void testCreate_sunriseMark() throws Exception {
    doXmlRoundtripTest("domain_create_sunrise_mark.xml");
  }

  @Test
  void testCreate_sunriseCodeWithMark() throws Exception {
    doXmlRoundtripTest("domain_create_sunrise_code_with_mark.xml");
  }

  @Test
  void testCreate_sunriseEncodedSignedMark() throws Exception {
    doXmlRoundtripTest("domain_create_sunrise_encoded_signed_mark.xml");
  }

  @Test
  void testCreate_fee() throws Exception {
    doXmlRoundtripTest("domain_create_fee.xml");
  }

  @Test
  void testCreate_emptyCommand() throws Exception {
    doXmlRoundtripTest("domain_create_empty.xml");
  }

  @Test
  void testCreate_missingNonRegistrantContacts() throws Exception {
    doXmlRoundtripTest("domain_create_missing_non_registrant_contacts.xml");
  }

  @Test
  void testCreate_cloneAndLinkReferences_withHosts() throws Exception {
    persistActiveHost("ns1.example.net");
    persistActiveHost("ns2.example.net");
    DomainCommand.Create create =
        (DomainCommand.Create) loadEppResourceCommand("domain_create.xml");
    create.cloneAndLinkReferences(fakeClock.now());
  }

  @Test
  void testCreate_cloneAndLinkReferences_failsWithContacts() throws Exception {
    persistActiveHost("ns1.example.net");
    persistActiveHost("ns2.example.net");
    DomainCommand.Create create =
        (DomainCommand.Create) loadEppResourceCommand("domain_create_with_contacts.xml");
    assertThrows(
        ContactsProhibitedException.class, () -> create.cloneAndLinkReferences(fakeClock.now()));
  }

  @Test
  void testCreate_cloneAndLinkReferences_failsWithRegistrant() throws Exception {
    DomainCommand.Create create =
        (DomainCommand.Create)
            loadEppResourceCommand("domain_create_missing_non_registrant_contacts.xml");
    assertThrows(
        RegistrantProhibitedException.class, () -> create.cloneAndLinkReferences(fakeClock.now()));
  }

  @Test
  void testCreate_emptyCommand_cloneAndLinkReferences() throws Exception {
    DomainCommand.Create create =
        (DomainCommand.Create) loadEppResourceCommand("domain_create_empty.xml");
    create.cloneAndLinkReferences(fakeClock.now());
  }

  @Test
  void testDelete() throws Exception {
    doXmlRoundtripTest("domain_delete.xml");
  }

  @Test
  void testUpdate() throws Exception {
    doXmlRoundtripTest("domain_update.xml");
  }

  @Test
  void testUpdate_emptyCommand() throws Exception {
    // This EPP command wouldn't be allowed for policy reasons, but should marshal/unmarshal fine.
    doXmlRoundtripTest("domain_update_empty.xml");
  }

  @Test
  void testUpdate_cloneAndLinkReferences_hosts() throws Exception {
    persistActiveHost("ns1.example.com");
    persistActiveHost("ns2.example.com");
    DomainCommand.Update update =
        (DomainCommand.Update) loadEppResourceCommand("domain_update.xml");
    update.cloneAndLinkReferences(fakeClock.now());
  }

  @Test
  void testUpdate_cloneAndLinkReferences_failsWithContacts() throws Exception {
    persistActiveHost("ns1.example.com");
    persistActiveHost("ns2.example.com");
    DomainCommand.Update update =
        (DomainCommand.Update) loadEppResourceCommand("domain_update_with_contacts.xml");
    assertThrows(
        ContactsProhibitedException.class, () -> update.cloneAndLinkReferences(fakeClock.now()));
  }

  @Test
  void testUpdate_emptyCommand_cloneAndLinkReferences() throws Exception {
    // This EPP command wouldn't be allowed for policy reasons, but should clone-and-link fine.
    DomainCommand.Update update =
        (DomainCommand.Update) loadEppResourceCommand("domain_update_empty.xml");
    update.cloneAndLinkReferences(fakeClock.now());
  }

  @Test
  void testInfo() throws Exception {
    doXmlRoundtripTest("domain_info.xml");
  }

  @Test
  void testInfo_sunrise() throws Exception {
    doXmlRoundtripTest("domain_info_sunrise.xml");
  }

  @Test
  void testCheck() throws Exception {
    doXmlRoundtripTest("domain_check.xml");
  }

  @Test
  void testCheck_avail() throws Exception {
    doXmlRoundtripTest("domain_check_avail.xml");
  }

  @Test
  void testCheck_claims() throws Exception {
    doXmlRoundtripTest("domain_check_claims.xml");
  }

  @Test
  void testCheck_fee() throws Exception {
    doXmlRoundtripTest("domain_check_fee.xml");
  }

  @Test
  void testTransferApprove() throws Exception {
    doXmlRoundtripTest("domain_transfer_approve.xml");
  }

  @Test
  void testTransferReject() throws Exception {
    doXmlRoundtripTest("domain_transfer_reject.xml");
  }

  @Test
  void testTransferCancel() throws Exception {
    doXmlRoundtripTest("domain_transfer_cancel.xml");
  }

  @Test
  void testTransferQuery() throws Exception {
    doXmlRoundtripTest("domain_transfer_query.xml");
  }

  @Test
  void testTransferRequest() throws Exception {
    doXmlRoundtripTest("domain_transfer_request.xml");
  }

  @Test
  void testTransferRequest_fee() throws Exception {
    doXmlRoundtripTest("domain_transfer_request_fee.xml");
  }

  @Test
  void testRenew() throws Exception {
    doXmlRoundtripTest("domain_renew.xml");
  }

  @Test
  void testRenew_fee() throws Exception {
    doXmlRoundtripTest("domain_renew_fee.xml");
  }

  /** Loads the EppInput from the given filename and returns its ResourceCommand element. */
  private ResourceCommand loadEppResourceCommand(String filename) throws Exception {
    EppInput eppInput = new EppLoader(this, filename).getEpp();
    return ((ResourceCommandWrapper) eppInput.getCommandWrapper().getCommand())
        .getResourceCommand();
  }
}
