import path, {dirname} from 'node:path'
import toBase64 from 'btoa'
import {readPackageAsync as readPackage} from 'read-pkg'
import size from 'any-size'
import {Octokit} from '@octokit/rest'
import pathExists from 'path-exists'
import writeJsonFile from 'write-json-file'
import yn from 'yn'
import is from '@sindresorhus/is'

import {fileURLToPath} from 'node:url'

import {isDomainId} from './utils.js'

const directoryName = dirname(fileURLToPath(import.meta.url))

const {version} = await readPackage()

const github = new Octokit({
  // GitHub personal access token
  auth: process.env.github_token,
  // User agent with version from package.json
  userAgent: `mit-license v${version}`
})

function getUserData({query, body}) {
  // If query parameters provided
  if (size(query) > 0) {
    return query
  }

  // If the data parsed as {'{data: "value"}': ''}
  if (size(body) === 1 && !Object.values(body)[0]) {
    return JSON.parse(Object.keys(body)[0])
  }

  // Fallback
  return body
}

const postRoute = async (request, response) => {
  const {hostname} = request

  // Get different parts of hostname (example: remy.mit-license.org -> ['remy', 'mit-license', 'org'])
  const parameters = hostname.split('.')

  // This includes the copyright, year, etc.
  const userData = getUserData(request)

  // If there isn't enough part of the hostname
  if (parameters.length < 2) {
    response.status(400).send('Please specify a subdomain in the URL.')
    return
  }

  // Extract the name from the URL
  const [id] = parameters

  if (!isDomainId(id)) {
    // Return a vague error intentionally
    response
      .status(400)
      .send(
        'User already exists - to update values, please send a pull request on https://github.com/remy/mit-license'
      )

    return
  }

  // Check if the user file exists in the users directory
  if (await pathExists(path.join(directoryName, '..', 'users', `${id}.json`))) {
    response
      .status(409)
      .send(
        'User already exists - to update values, please send a pull request on https://github.com/remy/mit-license'
      )
    return
  }

  if (userData.gravatar) {
    // Parse the string version of a boolean or similar
    userData.gravatar = yn(userData.gravatar, {lenient: true})
    if (is.undefined(userData.gravatar)) {
      response
        .status(400)
        .send(
          'The "gravatar" JSON property must be a boolean.'
        )
      return
    }
  }

  // File doesn't exist
  // If copyright property and key doesn't exist
  if (!userData.copyright) {
    response.status(400).send('JSON requires "copyright" property and value')
    return
  }

  try {
    await Promise.all([
      github.repos.createOrUpdateFileContents({
        owner: 'remy',
        repo: 'mit-license',
        path: `users/${id}.json`,
        message: `Automated creation of user ${id}.`,
        content: toBase64(JSON.stringify(userData, 0, 2)),
        committer: {
          name: 'MIT License Bot',
          email: 'remy@leftlogic.com'
        }
      }),
      writeJsonFile(path.join(directoryName, '..', 'users', `${id}.json`), userData, {indent: undefined})
    ])

    response.status(201).send(`MIT license page created: https://${hostname}`)
  } catch {
    response
      .status(500)
      .send(
        'Unable to create new user - please send a pull request on https://github.com/remy/mit-license'
      )
  }
}

// HTTP POST API
export default postRoute
