const { resolveServiceUrl } = require('../src/utilities/url-resolver');

describe('URL Resolver — DashCaddy service URL resolution', () => {
  const buildServiceUrl = jest.fn(id => `https://${id}.sami`);

  beforeEach(() => {
    buildServiceUrl.mockClear();
  });

  describe('Internet connectivity check', () => {
    it('always resolves "internet" to google.com regardless of config', () => {
      expect(resolveServiceUrl('internet', null, null, buildServiceUrl))
        .toBe('https://www.google.com');
      expect(buildServiceUrl).not.toHaveBeenCalled();
    });

    it('ignores service object for internet ID', () => {
      const service = { url: 'http://custom.test', isExternal: true, externalUrl: 'http://ext.test' };
      expect(resolveServiceUrl('internet', service, {}, buildServiceUrl))
        .toBe('https://www.google.com');
    });
  });

  describe('External services (seedhost, cloud-hosted)', () => {
    it('uses externalUrl for services marked isExternal', () => {
      const service = { isExternal: true, externalUrl: 'https://usw123.seedhost.eu/sami/radarr' };
      expect(resolveServiceUrl('radarr', service, {}, buildServiceUrl))
        .toBe('https://usw123.seedhost.eu/sami/radarr');
    });

    it('ignores isExternal if externalUrl is missing', () => {
      const service = { isExternal: true };
      expect(resolveServiceUrl('plex', service, {}, buildServiceUrl))
        .toBe('https://plex.sami');
    });
  });

  describe('Custom URL override on service', () => {
    it('uses service.url with http prefix as-is', () => {
      const service = { url: 'http://192.168.1.100:32400' };
      expect(resolveServiceUrl('plex', service, {}, buildServiceUrl))
        .toBe('http://192.168.1.100:32400');
    });

    it('uses service.url with https prefix as-is', () => {
      const service = { url: 'https://plex.mydomain.com' };
      expect(resolveServiceUrl('plex', service, {}, buildServiceUrl))
        .toBe('https://plex.mydomain.com');
    });

    it('prepends https:// to bare hostnames', () => {
      const service = { url: 'plex.sami' };
      expect(resolveServiceUrl('plex', service, {}, buildServiceUrl))
        .toBe('https://plex.sami');
    });
  });

  describe('DNS server resolution (Technitium, Pi-hole)', () => {
    it('resolves DNS server by ID from siteConfig', () => {
      const siteConfig = {
        dnsServers: {
          dns1: { ip: '192.168.254.204', port: 5380 },
          dns2: { ip: '100.74.102.61', port: 5380 },
        }
      };
      expect(resolveServiceUrl('dns1', null, siteConfig, buildServiceUrl))
        .toBe('http://192.168.254.204:5380');
      expect(resolveServiceUrl('dns2', null, siteConfig, buildServiceUrl))
        .toBe('http://100.74.102.61:5380');
    });

    it('defaults to port 5380 when port is omitted', () => {
      const siteConfig = { dnsServers: { dns1: { ip: '10.0.0.1' } } };
      expect(resolveServiceUrl('dns1', null, siteConfig, buildServiceUrl))
        .toBe('http://10.0.0.1:5380');
    });
  });

  describe('Fallback to buildServiceUrl (Caddy subdomain/subdirectory)', () => {
    it('falls back for local services with no special config', () => {
      resolveServiceUrl('radarr', { name: 'Radarr' }, {}, buildServiceUrl);
      expect(buildServiceUrl).toHaveBeenCalledWith('radarr');
    });

    it('works when service is null (top-card items)', () => {
      expect(resolveServiceUrl('sonarr', null, {}, buildServiceUrl))
        .toBe('https://sonarr.sami');
    });

    it('works when siteConfig is null', () => {
      expect(resolveServiceUrl('jellyfin', null, null, buildServiceUrl))
        .toBe('https://jellyfin.sami');
    });
  });

  describe('Priority chain — higher priority wins', () => {
    const fullService = {
      isExternal: true,
      externalUrl: 'https://external.test',
      url: 'http://custom.test',
    };
    const siteConfig = {
      dnsServers: { myservice: { ip: '10.0.0.1', port: 5380 } }
    };

    it('externalUrl wins over service.url and DNS', () => {
      expect(resolveServiceUrl('myservice', fullService, siteConfig, buildServiceUrl))
        .toBe('https://external.test');
    });

    it('service.url wins over DNS and fallback', () => {
      const service = { url: 'http://custom.test' };
      expect(resolveServiceUrl('myservice', service, siteConfig, buildServiceUrl))
        .toBe('http://custom.test');
    });

    it('DNS wins over fallback', () => {
      expect(resolveServiceUrl('myservice', null, siteConfig, buildServiceUrl))
        .toBe('http://10.0.0.1:5380');
    });
  });
});
