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

// 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('Nameservers - Basic Client Test', async () => {
  // Create a client with mock credentials
  const client = createTestClient(true);

  // Verify the client has the expected methods
  expect(client.ns.create).toBeTypeOf('function');
  expect(client.ns.delete).toBeTypeOf('function');
  expect(client.ns.getInfo).toBeTypeOf('function');
  expect(client.ns.update).toBeTypeOf('function');

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

// Parse domain into SLD and TLD
function parseDomain(domain: string): { sld: string, tld: string } {
  const parts = domain.split('.');
  const tld = parts.pop() || '';
  const sld = parts.join('.');
  return { sld, tld };
}

// Test nameserver creation and deletion
if (skipLiveTests) {
  tap.skip.test('Nameservers - Create and Delete Custom Nameserver', async () => {
    console.log('Skipping nameserver creation test - no credentials');
  });
} else {
  tap.test('Nameservers - Create and Delete Custom Nameserver', async (tools) => {
    // Set a timeout for the test
    tools.timeout(60000); // 60 seconds timeout

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

    // Parse the test domain
    const { sld, tld } = parseDomain(TEST_DOMAINS.DNS);

    // Create a unique nameserver name
    const nsName = `ns${Date.now()}.${TEST_DOMAINS.DNS}`;
    const nsIp = '192.168.1.1';

    try {
      console.log(await tools.coloredString(
        `Creating nameserver: ${nsName} with IP: ${nsIp}`,
        'cyan'
      ));

      // Create a new nameserver
      const createResult = await client.ns.create(sld, tld, nsName, nsIp);

      // Validate the result
      expect(createResult).toBeTrue();
      console.log(await tools.coloredString(
        `Successfully created nameserver: ${nsName} with IP: ${nsIp}`,
        'green'
      ));

      // Get nameserver info
      const nsInfo = await client.ns.getInfo(sld, tld, nsName);

      // Validate the info
      expect(nsInfo).toBeTypeOf('object');
      expect(nsInfo.nameserver).toEqual(nsName);
      expect(nsInfo.ip).toEqual(nsIp);

      console.log(await tools.coloredString(
        `Nameserver info:
        - Name: ${nsInfo.nameserver}
        - IP: ${nsInfo.ip}
        - Statuses: ${nsInfo.statuses.join(', ')}
        `,
        'green'
      ));

      // Update the nameserver IP
      const newIp = '192.168.1.2';
      console.log(await tools.coloredString(
        `Updating nameserver IP from ${nsIp} to ${newIp}`,
        'cyan'
      ));

      const updateResult = await client.ns.update(sld, tld, nsName, nsIp, newIp);

      // Validate the update result
      expect(updateResult).toBeTrue();
      console.log(await tools.coloredString(
        `Successfully updated nameserver IP from ${nsIp} to ${newIp}`,
        'green'
      ));

      // Verify the update
      const updatedInfo = await client.ns.getInfo(sld, tld, nsName);
      expect(updatedInfo.ip).toEqual(newIp);

      // Delete the nameserver
      console.log(await tools.coloredString(
        `Deleting nameserver: ${nsName}`,
        'cyan'
      ));

      const deleteResult = await client.ns.delete(sld, tld, nsName);

      // Validate the delete result
      expect(deleteResult).toBeTrue();
      console.log(await tools.coloredString(
        `Successfully deleted nameserver: ${nsName}`,
        'green'
      ));

    } catch (error) {
      console.error('Error in nameserver operations:', error);
      throw error;
    }
  });
}

// Test custom nameservers for domain
if (skipLiveTests) {
  tap.skip.test('Nameservers - Set Custom Nameservers for Domain', async () => {
    console.log('Skipping custom nameservers test - no credentials');
  });
} else {
  tap.test('Nameservers - Set Custom Nameservers for Domain', async (tools) => {
    // Set a timeout for the test
    tools.timeout(60000); // 60 seconds timeout

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

    // Get current DNS settings to restore later
    const currentHosts = await client.dns.getHosts(TEST_DOMAINS.DNS);

    try {
      // Set custom nameservers
      const customNameservers = [
        'dns1.namecheaphosting.com',
        'dns2.namecheaphosting.com'
      ];

      console.log(await tools.coloredString(
        `Setting custom nameservers for ${TEST_DOMAINS.DNS}: ${customNameservers.join(', ')}`,
        'cyan'
      ));

      const result = await client.dns.setCustom(TEST_DOMAINS.DNS, customNameservers);

      // Validate the result
      expect(result).toBeTrue();
      console.log(await tools.coloredString(
        `Successfully set custom nameservers for ${TEST_DOMAINS.DNS}`,
        'green'
      ));

      // Now restore the original DNS settings
      console.log(await tools.coloredString(
        `Restoring original DNS settings for ${TEST_DOMAINS.DNS}`,
        'cyan'
      ));

      const restoreResult = await client.dns.setHosts(
        TEST_DOMAINS.DNS,
        currentHosts.map(host => ({
          hostName: host.name,
          recordType: host.type as any,
          address: host.address,
          mxPref: host.type === 'MX' ? host.mxPref : undefined,
          ttl: host.ttl
        }))
      );

      expect(restoreResult).toBeTrue();
      console.log(await tools.coloredString(
        `Successfully restored original DNS settings for ${TEST_DOMAINS.DNS}`,
        'green'
      ));

    } catch (error) {
      console.error('Error in custom nameserver operations:', error);

      // Try to restore original settings if there was an error
      try {
        await client.dns.setHosts(
          TEST_DOMAINS.DNS,
          currentHosts.map(host => ({
            hostName: host.name,
            recordType: host.type as any,
            address: host.address,
            mxPref: host.type === 'MX' ? host.mxPref : undefined,
            ttl: host.ttl
          }))
        );
        console.log(await tools.coloredString(
          'Restored original DNS settings after error',
          'yellow'
        ));
      } catch (restoreError) {
        console.error('Failed to restore original DNS settings:', restoreError);
      }

      throw error;
    }
  });
}

// Start the tests
tap.start();