import { RepoData, SearchCriteria } from './types';

export const GET_REPO = `
  query GetRepo($org: String!, $repo: String!) {
    repository(owner: $org, name: $repo) {
      id
      name
      description
      viewerHasStarred
      stargazers {
        totalCount
      }
    }
  }
`;

type GetRepoResponse = {
  data: RepoData;
};

export async function getRepo(searchCriteria: SearchCriteria) {
  const response = await fetch(process.env.REACT_APP_GITHUB_URL!, {
    method: 'POST',
    body: JSON.stringify({
      query: GET_REPO,
      variables: {
        org: searchCriteria.org,
        repo: searchCriteria.repo,
      },
    }),
    headers: {
      'Content-Type': 'application/json',
      Authorization: `bearer ${process.env.REACT_APP_GITHUB_PAT}`,
    },
  });
  const body = (await response.json()) as unknown;
  assertIsGetRepoResponse(body);
  return body.data;
}

function assertIsGetRepoResponse(response: any): asserts response is GetRepoResponse {
  if (typeof response !== 'object' || response === null) {
    throw new Error("Odpowiedź nie jest obiektem");
  }
  if (!('data' in response)) {
    throw new Error("Odpowiedź nie zawiera danych");
  }
  if (typeof response.data !== 'object') {
    throw new Error('Odpowiedź nie jest obiektem');
  }
  if (!('repository' in response.data)) {
    throw new Error("Dane nie zawierają repozytorium");
  }
  if (typeof response.data.repository !== 'object') {
    throw new Error('Repozytorium nie jest obiektem');
  }
  if (!('id' in response.data.repository)) {
    throw new Error("Repozytorium nie zawiera id");
  }
  if (typeof response.data.repository.id !== 'string') {
    throw new Error('Id repozytorium nie jest ciągiem znaków');
  }
  if (!('name' in response.data.repository)) {
    throw new Error("Repozytorium nie zawiera nazwy");
  }
  if (typeof response.data.repository.name !== 'string') {
    throw new Error('Nazwa repozytorium nie jest ciągiem znaków');
  }
  if (!('description' in response.data.repository)) {
    throw new Error("Repozytorium nie zawiera opisu");
  }
  if (typeof response.data.repository.description !== 'string') {
    throw new Error('Opis repozytorium nie jest ciągiem znaków');
  }
  if (!('viewerHasStarred' in response.data.repository)) {
    throw new Error("Repozytorium nie zawiera informacji o gwiazdkach od widza");
  }
  if (typeof response.data.repository.viewerHasStarred !== 'boolean') {
    throw new Error('Informacja o gwiazdkach od widza w repozytorium nie jest wartością logiczną');
  }
  if (!('stargazers' in response.data.repository)) {
    throw new Error("Repozytorium nie zawiera informacji o obserwujących");
  }
  if (typeof response.data.repository.stargazers !== 'object') {
    throw new Error('Obserwujący repozytorium nie są obiektem');
  }
  if (!('totalCount' in response.data.repository.stargazers)) {
    throw new Error("Obserwujący repozytorium nie zawierają całkowitej liczby");
  }
  if (typeof response.data.repository.stargazers.totalCount !== 'number') {
    throw new Error('Całkowita liczba obserwujących repozytorium nie jest liczbą');
  }
}
