import { describe, expect, it } from 'vitest';

import { GITHUB_PAT_SETTINGS_URL, getGitHubCompareUrl, gitRemoteUrlToWeb, isGitHubUrl, isValidGitUrl } from './git-url.js';

describe('isValidGitUrl', () => {
  it.each([
    'https://github.com/org/repo.git',
    'https://github.com/org/repo',
    'http://gitlab.com/org/repo.git',
    'git@github.com:org/repo.git',
    'git@gitlab.com:org/repo'
  ])('returns true for %s', (url) => {
    expect(isValidGitUrl(url)).toBe(true);
  });

  it.each(['', 'not-a-url', 'ftp://github.com/org/repo', 'https://'])('returns false for %j', (url) => {
    expect(isValidGitUrl(url)).toBe(false);
  });

  it('trims whitespace', () => {
    expect(isValidGitUrl('  https://github.com/org/repo  ')).toBe(true);
  });
});

describe('isGitHubUrl', () => {
  it.each(['https://github.com/org/repo.git', 'https://github.com/org/repo', 'git@github.com:org/repo.git'])(
    'returns true for %s',
    (url) => {
      expect(isGitHubUrl(url)).toBe(true);
    }
  );

  it.each(['https://gitlab.com/org/repo', 'git@bitbucket.org:org/repo.git', 'https://example.com/org/repo', 'not-a-url'])(
    'returns false for %s',
    (url) => {
      expect(isGitHubUrl(url)).toBe(false);
    }
  );

  it('is case-insensitive on the host', () => {
    expect(isGitHubUrl('https://GitHub.COM/org/repo')).toBe(true);
  });
});

describe('gitRemoteUrlToWeb', () => {
  it.each<[string, string]>([
    ['https://github.com/org/repo.git', 'https://github.com/org/repo'],
    ['https://github.com/org/repo', 'https://github.com/org/repo'],
    ['http://gitlab.com/org/repo.git', 'http://gitlab.com/org/repo'],
    ['git@github.com:org/repo.git', 'https://github.com/org/repo'],
    ['git@gitlab.com:group/sub/repo.git', 'https://gitlab.com/group/sub/repo']
  ])('converts %s → %s', (input, expected) => {
    expect(gitRemoteUrlToWeb(input)).toBe(expected);
  });

  it('returns null for unconvertible URLs', () => {
    expect(gitRemoteUrlToWeb('not-a-url')).toBeNull();
  });
});

describe('getGitHubCompareUrl', () => {
  const base = { fromBranch: 'feature/cool', toBranch: 'main' };

  it('builds a GitHub compare URL', () => {
    expect(
      getGitHubCompareUrl({
        gitRemoteUrl: 'https://github.com/org/repo.git',
        ...base
      })
    ).toBe('https://github.com/org/repo/compare/main...feature%2Fcool');
  });

  it('appends title and body', () => {
    expect(
      getGitHubCompareUrl({
        gitRemoteUrl: 'https://github.com/org/repo.git',
        ...base,
        title: 'My PR',
        body: '## Summary'
      })
    ).toBe('https://github.com/org/repo/compare/main...feature%2Fcool?expand=1&title=My+PR&body=%23%23+Summary');
  });

  it('returns null for non-GitHub URLs', () => {
    expect(
      getGitHubCompareUrl({
        gitRemoteUrl: 'https://gitlab.com/org/repo',
        ...base
      })
    ).toBeNull();
  });

  it('returns null for unconvertible URLs', () => {
    expect(getGitHubCompareUrl({ gitRemoteUrl: 'not-a-url', ...base })).toBeNull();
  });
});

describe('GITHUB_PAT_SETTINGS_URL', () => {
  it('is a valid URL', () => {
    expect(GITHUB_PAT_SETTINGS_URL).toBe('https://github.com/settings/tokens');
  });
});
