import fetch from 'node-fetch'
import { logInfo, logError } from './log'
import { PlatformConfig, ContainerDeploymentRequest } from 'types'

export const Matchers = {
  host: host => ({ host: [host] }),
  path: path => ({ path: [path] })
}

const Handlers = {
  reverseProxy: upstreamPort => ({
    handler: 'reverse_proxy',
    upstreams: [{ dial: `localhost:${upstreamPort}` }]
  }),
  subroute: routes => ({
    handler: 'subroute',
    routes
  })
}

export class CaddyClient {

  static deploy(platformConfig: PlatformConfig, deploymentRequest: ContainerDeploymentRequest) {

    const url = `${deploymentRequest.subdomain}.${platformConfig.activeEnvironment}.${platformConfig.domain}`

    logInfo({ message: `[CaddyClient] Updating caddy config to route ${url} to localhost:${deploymentRequest.hostPort}` })

    return fetch(`http://localhost:2019/config/apps/http/servers/${platformConfig.ciServerName}/routes/0/handle`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(Handlers.subroute([
        {
          match: [Matchers.host(url)],
          handle: [Handlers.subroute([{ handle: [Handlers.reverseProxy(deploymentRequest.hostPort)]}])]
        }
      ]))
    })
    .catch(error => logError({  message: `[CaddyClient] Could not update caddy config to include ${url}`, error }))
  }

  static applyDefaultServerConfig(platformConfig: PlatformConfig) {
    logInfo({  message: '[CaddyClient] Applying default caddy config' })
    return fetch('http://localhost:2019/load', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        apps: {
          http: {
            servers: {
              [platformConfig.ciServerName]: {
                listen: [':80', ':443'],
                routes: [
                  {
                    match: [Matchers.host(`*.${platformConfig.activeEnvironment}.${platformConfig.domain}`)],
                    handle: [Handlers.subroute([
                      {
                        match: [Matchers.host(`${platformConfig.ciSubDomain}.${platformConfig.activeEnvironment}.${platformConfig.domain}`)],
                        handle: [Handlers.subroute([{ handle: [Handlers.reverseProxy(platformConfig.ciInternalServerPort)]}])]
                      }
                    ])],
                    terminal: true
                  }
                ]
              }
            }
          },
          tls: {
            automation: {
              policies: [
                {
                  subjects:[`*.${platformConfig.activeEnvironment}.${platformConfig.domain}`],
                  issuers:[
                    {
                      challenges:{
                        dns:{
                          provider:{
                            'max_retries': 10,
                            name: 'route53',
                            'aws_profile': 'ci-client'
                          }
                        }
                      },
                      module: 'acme'
                    },
                    {
                      challenges:{
                        dns:{
                          provider:{
                            'max_retries': 10,
                            name: 'route53'
                          }
                        }
                      },
                      module: 'zerossl'
                    }
                  ]
                }
              ]
            }
          }
        }
      })
    })
      .catch(error => logError({  message: '[CaddyClient] Could not apply default caddy config', error }))
  }

}
