/**
 * Test file for Namecheap domain contact management
 */
import { expect, tap } from '@push.rocks/tapbundle';
import { createTestClient, TEST_DOMAINS, hasRealCredentials } from './config.js';

// Define a simplified contact info interface for the test
interface IContactInfo {
  FirstName?: string;
  LastName?: string;
  Address1?: string;
  Address2?: string;
  City?: string;
  StateProvince?: string;
  PostalCode?: string;
  Country?: string;
  Phone?: string;
  EmailAddress?: string;
  [key: string]: string | undefined;
}

// Skip live API tests if no real credentials
const skipLiveTests = !hasRealCredentials();

// Always run this test to ensure the file doesn't fail when all other tests are skipped
tap.test('Contacts - Basic Client Test', async () => {
  // Create a client with mock credentials
  const client = createTestClient(true);

  // Verify the client has the expected methods
  expect(client.domains.getContacts).toBeTypeOf('function');
  expect(client.domains.setContacts).toBeTypeOf('function');

  // This test always passes
  expect(true).toBeTrue();
});

// Test getting domain contacts
if (skipLiveTests) {
  tap.skip.test('Contacts - Get Domain Contacts', async () => {
    console.log('Skipping get contacts test - no credentials');
  });
} else {
  tap.test('Contacts - Get Domain Contacts', async (tools) => {
    // Set a timeout for the test
    tools.timeout(15000); // 15 seconds timeout

    // Create a new client instance
    const client = createTestClient();

    try {
      console.log(await tools.coloredString(
        `Getting contacts for domain: ${TEST_DOMAINS.INFO}`,
        'cyan'
      ));

      // Get contact information for a domain
      const contacts = await client.domains.getContacts(TEST_DOMAINS.INFO);

      // Validate the result
      expect(contacts).toBeTypeOf('object');
      expect(contacts.registrant).toBeTypeOf('object');
      expect(contacts.tech).toBeTypeOf('object');
      expect(contacts.admin).toBeTypeOf('object');
      expect(contacts.auxBilling).toBeTypeOf('object');

      // Log the contact information with colored output
      console.log(await tools.coloredString('Registrant Contact:', 'green'));
      logContactInfo(tools, contacts.registrant);

      console.log(await tools.coloredString('Technical Contact:', 'green'));
      logContactInfo(tools, contacts.tech);

      console.log(await tools.coloredString('Administrative Contact:', 'green'));
      logContactInfo(tools, contacts.admin);

      console.log(await tools.coloredString('Billing Contact:', 'green'));
      logContactInfo(tools, contacts.auxBilling);
    } catch (error) {
      console.error('Error getting domain contacts:', error);
      throw error;
    }
  });
}

// Test setting domain contacts
if (skipLiveTests) {
  tap.skip.test('Contacts - Set Domain Contacts', async () => {
    console.log('Skipping set contacts test - no credentials');
  });
} else {
  tap.test('Contacts - Set Domain Contacts', async (tools) => {
    // Set a timeout for the test
    tools.timeout(30000); // 30 seconds timeout

    // Create a new client instance
    const client = createTestClient();

    try {
      // First, get the current contacts to use as a base
      console.log(await tools.coloredString(
        `Getting current contacts for domain: ${TEST_DOMAINS.INFO}`,
        'cyan'
      ));

      const currentContacts = await client.domains.getContacts(TEST_DOMAINS.INFO);

      // Make a copy of the contacts to modify
      const updatedContacts = {
        registrant: { ...currentContacts.registrant },
        tech: { ...currentContacts.tech },
        admin: { ...currentContacts.admin },
        auxBilling: { ...currentContacts.auxBilling }
      };

      // Update the phone number for all contacts
      // This is a safe change that shouldn't cause issues
      const timestamp = Date.now();
      const newPhone = `+1.555${timestamp.toString().slice(-7)}`;

      updatedContacts.registrant.Phone = newPhone;
      updatedContacts.tech.Phone = newPhone;
      updatedContacts.admin.Phone = newPhone;
      updatedContacts.auxBilling.Phone = newPhone;

      console.log(await tools.coloredString(
        `Updating contacts with new phone number: ${newPhone}`,
        'cyan'
      ));

      // Set the updated contacts
      const success = await client.domains.setContacts(TEST_DOMAINS.INFO, updatedContacts);

      // Validate the result
      expect(success).toBeTrue();

      console.log(await tools.coloredString(
        'Successfully updated domain contacts',
        'green'
      ));

      // Verify the changes
      console.log(await tools.coloredString(
        'Verifying contact changes...',
        'cyan'
      ));

      const verifyContacts = await client.domains.getContacts(TEST_DOMAINS.INFO);

      expect(verifyContacts.registrant.Phone).toEqual(newPhone);
      expect(verifyContacts.tech.Phone).toEqual(newPhone);
      expect(verifyContacts.admin.Phone).toEqual(newPhone);
      expect(verifyContacts.auxBilling.Phone).toEqual(newPhone);

      console.log(await tools.coloredString(
        'Contact changes verified successfully',
        'green'
      ));
    } catch (error) {
      console.error('Error setting domain contacts:', error);
      throw error;
    }
  });
}

// Test validation of contact information
tap.test('Contacts - Validate Contact Information', async () => {
  // Create a client with mock credentials
  const client = createTestClient(true);

  // Create incomplete contact information
  const incompleteContacts = {
    registrant: {
      FirstName: 'Test',
      LastName: 'User'
      // Missing required fields
    }
  };

  // Attempt to set contacts with incomplete information
  let validationError: Error | null = null;
  try {
    await client.domains.setContacts('example.com', incompleteContacts);
    // If we get here, the validation failed to catch the incomplete information
    expect(false).toBeTrue(); // This should never execute
  } catch (error) {
    validationError = error as Error;
  }

  // Verify we got an error
  expect(validationError).not.toBeNull();

  // Create complete contact information
  const completeContacts = {
    registrant: {
      FirstName: 'Test',
      LastName: 'User',
      Address1: '123 Test St',
      City: 'Test City',
      StateProvince: 'CA',
      PostalCode: '12345',
      Country: 'US',
      Phone: '+1.5555555555',
      EmailAddress: 'test@example.com'
    }
  };

  // This should not throw a validation error
  // (though it will fail at the API level since we're using mock credentials)
  let apiError: Error | null = null;
  try {
    await client.domains.setContacts('example.com', completeContacts);
  } catch (error) {
    apiError = error as Error;
  }

  // Verify we got an error (API error, not validation error)
  expect(apiError).not.toBeNull();
});

// Helper function to log contact information
async function logContactInfo(tools: any, contact: IContactInfo): Promise<void> {
  if (!contact) {
    console.log(await tools.coloredString('No contact information available', 'blue'));
    return;
  }

  if (contact.FirstName && contact.LastName) {
    console.log(await tools.coloredString(`Name: ${contact.FirstName} ${contact.LastName}`, 'blue'));
  }

  if (contact.EmailAddress) {
    console.log(await tools.coloredString(`Email: ${contact.EmailAddress}`, 'blue'));
  }

  if (contact.Phone) {
    console.log(await tools.coloredString(`Phone: ${contact.Phone}`, 'blue'));
  }

  if (contact.Address1) {
    console.log(await tools.coloredString(
      `Address: ${contact.Address1}${contact.Address2 ? ', ' + contact.Address2 : ''}, ${contact.City}, ${contact.StateProvince}, ${contact.PostalCode}, ${contact.Country}`,
      'blue'
    ));
  }
}

// Start the tests
tap.start();