import {
  type ReposConfiguration,
  type GitConfig,
} from './configTypes.ts'
import { type Repository} from './dataTypes.ts'
import util from 'util'
import childProcess from 'child_process'
import cloneUrl from './vcses/git/helpers.ts'

import { addBranchToCommitsMap } from './vcses/git/operations.ts'
import { getLocation} from './helpers.ts'
import { getFileList } from './vcses/git/operations.ts'

const exec = util.promisify(childProcess.exec)

const getBranchNames = (repoConfig: GitConfig): Array<string> => {
  return repoConfig.branchesToPull.map((branch) => {
    if (typeof branch === "string") {
      return branch
    }
    else {
      return "" // todo
    }
  })
}

let cachedRepos: Array<Repository> | null = null

const repos: (reposConfig: ReposConfiguration) => Promise<Array<Repository>> = async (reposConfig) => {
  if (cachedRepos !== null) { return cachedRepos }

  const repoNames = Object.keys(reposConfig.repos)
  cachedRepos = []

  for (const repoName of repoNames) {
    const branchNames = getBranchNames(reposConfig.repos[repoName])
    const commits: Repository['commits'] = new Map()
    for (const branchName of branchNames) {
      const repoLocation = getLocation(reposConfig, repoName)
      await addBranchToCommitsMap(branchName, repoLocation, commits)
    }

    const branches = await Promise.all(branchNames.map(async (branchName) => {
      const repoLocation = getLocation(reposConfig, repoName)
      const branchHeadRes = await exec(`git -C ${repoLocation} show-ref refs/heads/${branchName}`)
      const branchHead = branchHeadRes.stdout.split(" ")[0]
      return {
        name: branchName,
        head: branchHead,
        fileList: await getFileList(branchName, repoLocation)
      }
    }))

    cachedRepos.push({
      name: repoName,
      description: reposConfig.repos[repoName].description,
      branches,
      cloneUrl: cloneUrl.cloneUrl(reposConfig.baseUrl, repoName),
      defaultBranch: reposConfig.repos[repoName].defaultBranch,
      tags: [], // todo
      commits,
    })
  }

  return cachedRepos
}

export default repos
