import {Ajv} from 'ajv'
import {ReposConfiguration, ReposConfigurationWithDefaultsApplied} from './src/configTypes.ts'
import ConfigSchema from './schemas/ReposConfiguration.json' with { type: 'json' }

const ajv = new Ajv()

function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();

  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

export const getConfig = (userConfiguration: ReposConfiguration)
                         : ReposConfigurationWithDefaultsApplied => {
  const validator = ajv.compile(ConfigSchema)
  const valid = validator(userConfiguration)
  if (!valid) {
    throw new Error(validator.errors.map(error => `config object at ${error.instancePath.replaceAll("/", ".")}: ${error.message}\n${Object.values(error.params).toString()}`).join("\n"))
  }

  const defaults = {
    path: '/repos',
    defaultTemplate: {
      enabled: true,
      allRepositoriesPageTitle: "All Repositories",
      colors: {
        languageGraph: [
          { light: '#ff549bff' },
          { light: '#8ec323ff' },
          { light: '#f8e276ff' },
          { light: '#f49530ff' },
          { light: '#edabb8ff' },
          { light: '#e273faff' },
          { light: '#852cdfff', dark: '#B673FA' },
        ]
      }
    }
  }

  const userRepos = userConfiguration.repos

  const reposConfiguration = mergeDeep({}, defaults, userConfiguration)

  const repoDefaults = {
    defaultBranch: 'main',
    branches: ['**'],
    tags: ['**'],
    languageExtensions: {},
    defaultTemplate: {
      homepageButtons: [],
    }
  }

  const repos = {}
  for (const repoName in userRepos) {
    const res = mergeDeep({}, repoDefaults, userRepos[repoName])
    repos[repoName] = res
  }

  reposConfiguration['repos'] = repos
  return reposConfiguration
}
