import fs, {promises as fsp} from 'fs';
import {join} from 'path';
import fecha from 'fecha';
import gitlab, {Gitlab} from 'gitlab';

type GitLab = InstanceType<typeof Gitlab>;

interface Config {
  gitlabToken: string;
}

async function entry(): Promise<void> {
  await Promise.all([getCommits(), getIssues(), getMergeRequests()]);
}

async function setupGitLabAPI(): Promise<GitLab> {
  const config: Config = await getConfig();
  const api: GitLab = new Gitlab({token: config.gitlabToken});
  return api;
}

async function setupTemporaryDirectory(): Promise<string> {
  const temporaryDirectory: string = join(__dirname, '../../temp/');
  await fsp.mkdir(temporaryDirectory + 'data/', {recursive: true});
  return temporaryDirectory;
}

async function getConfig(): Promise<Config> {
  const config: Config = JSON.parse(
    await fsp.readFile(join(__dirname, '../../config.json'), 'utf8')
  );
  return config;
}

export async function getCommits(): Promise<any[]> {
  const temporaryDirectory: string = await setupTemporaryDirectory();
  const api: GitLab = await setupGitLabAPI();
  const project: gitlab.ProjectSchema = await api.Projects.show(
    'tildes/tildes'
  );
  const commitsPath: string = join(
    temporaryDirectory,
    `data/commits (${fecha.format(new Date(), 'YYYY-MM-DD')}).json`
  );
  let commits: any[];
  if (fs.existsSync(commitsPath)) {
    console.log('Commits JSON file available for today, using local file.');
    commits = JSON.parse(await fsp.readFile(commitsPath, 'utf8'));
  } else {
    console.log('Downloading all commits from GitLab.');
    commits = (await api.Commits.all(project.id, {
      ref_name: 'master',
      with_stats: true
    })) as any[];
    await fsp.writeFile(commitsPath, JSON.stringify(commits, null, 2));
  }

  return commits;
}

export async function getIssues(): Promise<any[]> {
  const temporaryDirectory: string = await setupTemporaryDirectory();
  const api: GitLab = await setupGitLabAPI();
  const project: gitlab.ProjectSchema = await api.Projects.show(
    'tildes/tildes'
  );
  const issuesPath: string = join(
    temporaryDirectory,
    `data/issues (${fecha.format(new Date(), 'YYYY-MM-DD')}).json`
  );
  let issues: any[];
  if (fs.existsSync(issuesPath)) {
    console.log('Issues JSON file available for today, using local file.');
    issues = JSON.parse(await fsp.readFile(issuesPath, 'utf8'));
  } else {
    console.log('Downloading all issues from GitLab.');
    issues = (await api.Issues.all({projectId: project.id})) as any[];
    await fsp.writeFile(issuesPath, JSON.stringify(issues, null, 2));
  }

  issues.sort((a, b) => a.iid - b.iid);
  return issues;
}

export async function getMergeRequests(): Promise<any[]> {
  const temporaryDirectory: string = await setupTemporaryDirectory();
  const api: GitLab = await setupGitLabAPI();
  const project: gitlab.ProjectSchema = await api.Projects.show(
    'tildes/tildes'
  );
  const mergeRequestsPath: string = join(
    temporaryDirectory,
    `data/merge requests (${fecha.format(new Date(), 'YYYY-MM-DD')}).json`
  );
  let mergeRequests: any[];
  if (fs.existsSync(mergeRequestsPath)) {
    console.log(
      'Merge Requests JSON file available for today, using local file.'
    );
    mergeRequests = JSON.parse(await fsp.readFile(mergeRequestsPath, 'utf8'));
  } else {
    console.log('Downloading all merge requests from GitLab.');
    mergeRequests = (await api.MergeRequests.all({
      projectId: project.id
    })) as any[];
    await fsp.writeFile(
      mergeRequestsPath,
      JSON.stringify(mergeRequests, null, 2)
    );
  }

  mergeRequests.sort((a, b) => a.iid - b.iid);
  return mergeRequests;
}

if (require.main === module) {
  void entry();
}
