import { describe, expect, it } from 'bun:test';
import { checkServiceUrl } from './url';

// The instance may be anywhere. These tests are mostly about what must NOT be rejected — every case
// below is an ordinary self-hosted setup, and treating any of them as invalid would send someone to
// the docs for no reason.

describe('accepts wherever the service actually is', () => {
  const ok = [
    'https://photos.example.com', // remote, behind a proxy on 443
    'http://10.0.0.5:8096', // another host on the LAN, standard port
    'http://100.64.0.1:19999', // tailnet address, arbitrary port
    'https://example.com/immich', // sharing a domain, served under a path
    'http://127.0.0.1:9091', // same machine, which is allowed — just not assumed
    'http://immich:2283', // a docker network hostname
  ];

  for (const url of ok) {
    it(`accepts ${url}`, () => {
      expect(checkServiceUrl(url).ok).toBe(true);
    });
  }
});

describe('normalises what is untidy', () => {
  it('strips a trailing slash', () => {
    // `${url}/api/x` would otherwise double the separator — accepted by some servers, 404 by others,
    // which is the kind of difference that reproduces on one machine and not another.
    const result = checkServiceUrl('https://photos.example.com/');
    expect(result.ok && result.url).toBe('https://photos.example.com');
  });

  it('drops a query string, which is where a token would hide', () => {
    const result = checkServiceUrl('https://x.example.com/?token=secret');
    expect(result.ok && result.url).toBe('https://x.example.com');
  });

  it('keeps a path, because a service under a prefix is normal', () => {
    const result = checkServiceUrl('https://example.com/immich/');
    expect(result.ok && result.url).toBe('https://example.com/immich');
  });
});

describe('rejects only what cannot work', () => {
  it('names the missing scheme rather than saying "invalid"', () => {
    // The commonest mistake: people type what they type into a browser.
    const result = checkServiceUrl('photos.example.com');
    expect(result.ok).toBe(false);
    if (result.ok) throw new Error('unreachable');
    expect(result.error).toContain('https://photos.example.com');
  });

  it('refuses credentials in the URL', () => {
    // They would land in a column meant for a location — outside the encrypted secret, and in every
    // log line that ever prints the URL.
    expect(checkServiceUrl('https://user:pass@x.example.com').ok).toBe(false);
  });

  it('refuses a scheme nothing here speaks', () => {
    expect(checkServiceUrl('ftp://x.example.com').ok).toBe(false);
  });

  it('refuses empty', () => {
    expect(checkServiceUrl('   ').ok).toBe(false);
  });
});
