import { resolve } from 'path'
import { readFileSync } from 'fs'
import {
  SupportedEnvironments,
  ContainerDeploymentRequest,
  DeploymentTemplate,
  ContainerDeploymentTemplate,
  SupportedDeploymentTypes
} from 'types'
import { PlatformTemplateService } from 'platform-template'
import { PlatformConfigService } from 'platform-config'
import { CaddyClient } from './caddy-client'
import { DockerClient } from './docker-client'
import { DeploymentQueueClient } from './deployment-queue-client'
import { CiRestApi } from './ci-rest-api'
import { logInfo, logError } from 'log'


// journalctl -u service-name.service
export class PlatformClient {

  static start(platformTemplatesFilePath: string) {
    PlatformTemplateService.readFromFile(platformTemplatesFilePath).then(([firstPlatformTemplateFound]) => {
      const platformConfig = PlatformConfigService.from(firstPlatformTemplateFound)

      CiRestApi.start(platformConfig)
      CaddyClient.applyDefaultServerConfig(platformConfig)

      DeploymentQueueClient.pollForDeploymentRequests(
        platformConfig,
        (deploymentRequest: ContainerDeploymentRequest) => {
          DockerClient.deploy(platformConfig, deploymentRequest)
          CaddyClient.deploy(platformConfig, deploymentRequest)
          return Promise.resolve()
        }
      )

    })
    .catch(error => logError({  message: '[PlatformClient] Could not start the deployment platform', error }))
  }

  //eslint-disable-next-line max-params
  static deploy({
    username,
    authentication,
    targetEnvironment,
    pathToPlatformTemplates,
    pathToOssyFile
  }) {

    const platformConfigRequest = PlatformTemplateService.readFromFile(pathToPlatformTemplates)
      .then(templates => templates.map(x => ({ ...x, activeEnvironment: targetEnvironment })))
      .then(templates => templates.map(x => PlatformConfigService.from(x)))

    const deploymentTemplatesRequest = PlatformClient.getDeploymentTemplates(pathToOssyFile)

    return Promise.all([ platformConfigRequest, deploymentTemplatesRequest ])
      .then(([platformConfigs, deploymentTemplates]) => {
        deploymentTemplates.map(deploymentTemplate => {

          const platformConfig = platformConfigs.find(config => config.platformName === deploymentTemplate.targetDeploymentPlatform)

          if (!platformConfig) {
            logError({ message: `[PlatformClient] Could not find a deployment platform with the name ${deploymentTemplate.targetDeploymentPlatform}` })
            return Promise.reject()
          }

          process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'

          if (deploymentTemplate.type !== SupportedDeploymentTypes.Container) {
            logError({ message: `[PlatformClient] Unsupported deployment type of ${deploymentTemplate.type}` })
            return Promise.reject()
          }

          const deploymentRequest: ContainerDeploymentRequest = {
            ...deploymentTemplate as ContainerDeploymentTemplate,
            env: PlatformClient.getEnvironmentVariables(targetEnvironment, deploymentTemplate),
            username: username,
            authentication: authentication
          }

          return DeploymentQueueClient.sendDeploymentRequest(platformConfig, deploymentRequest)

        })
      })
      .catch(error => logError({ message: '[PlatformClient] Could not send deployment request', error }))
  }

  static getDeploymentTemplates(pathToOssyFile: string): Promise<DeploymentTemplate[]> {
    const ossyfile = JSON.parse(readFileSync(resolve(pathToOssyFile), 'utf8'))
    return Promise.resolve(ossyfile.deployments || [])
  }

  static getEnvironmentVariables(targetEnvironment: SupportedEnvironments, deploymentRequest: DeploymentTemplate) {
    const envs = deploymentRequest.env || {}
    return {
      ...(envs.shared || {}),
      ...(envs[targetEnvironment] || {})
    }
  }

}
