// @ts-check

// Grab the schema for reaction out of the node_modules
// to see if it is a subset of the production schema
//
// Used both by Danger during the deploy PR, and also
// before the deployment on circle
//
const { readFileSync } = require("fs")
const {
  introspectionQuery,
  buildClientSchema,
  printSchema,
  buildSchema,
  findBreakingChanges,
} = require("graphql")

const fetch = require("isomorphic-fetch")

const downloadMetaphysicsSchema = async endpoint => {
  const postBody = {
    query: introspectionQuery,
    operationName: "IntrospectionQuery",
  }

  const response = await fetch(endpoint, {
    method: "POST",
    body: JSON.stringify(postBody),
    headers: {
      "Content-Type": "application/json",
    },
  })
  const { data } = await response.json()
  // commentDescriptions is hidden
  // @ts-ignore
  return printSchema(buildClientSchema(data), { commentDescriptions: true })
}

const downloadGitHubReaction = async release => {
  const response = await fetch(
    `https://github.com/artsy/reaction/raw/v${release}/data/schema.graphql`
  )

  const body = await response.text()
  return body
}

const getBreakingChanges = async (metaphysicsEnv) => {
  const packageJSON = JSON.parse(
    readFileSync(__dirname + "/../package.json", "utf8")
  )
  const reactionVersion = packageJSON["dependencies"]["@artsy/reaction"]
  const reactionSchema = await downloadGitHubReaction(reactionVersion)
  const metaphyicsSchema = await downloadMetaphysicsSchema(`https://metaphysics-${metaphysicsEnv}.artsy.net/`)
  return findBreakingChanges(
    buildSchema(metaphyicsSchema),
    buildSchema(reactionSchema)
  )
}

module.exports = {
  getBreakingChanges,
}

// @ts-ignore
if (require.main === module) {
  // When this is being called as a script via `node scripts/validate_schemas.js`
  if (process.argv.length != 3) {
    console.log('This script must be called with either "staging" or "production"')
    process.exitCode = 1
  } else {
    getBreakingChanges(process.argv[2]).then(changes => {
      if (changes.length) {
        process.exitCode = 1
        console.error(
          `Failing due to breaking changes between Force and Metaphysics ${process.argv[2]}\n\n`
        )
        console.error(changes)
        console.error(
          `\n\nYou should deploy metaphysics ${process.argv[2]}, and re-deploy force`
        )
      } else {
        console.log("No breaking changes found!")
      }
    })
  }
}

// @ts-check

// Grab the schema for reaction out of the node_modules
// to see if it is a subset of the production schema
//
// Used both by Danger during the deploy PR, and also
// before the deployment on circle
//
const { readFileSync } = require("fs")
const {
  introspectionQuery,
  buildClientSchema,
  printSchema,
  buildSchema,
  findBreakingChanges,
} = require("graphql")

const fetch = require("isomorphic-fetch")

const downloadMetaphysicsSchema = async endpoint => {
  const postBody = {
    query: introspectionQuery,
    operationName: "IntrospectionQuery",
  }

  const response = await fetch(endpoint, {
    method: "POST",
    body: JSON.stringify(postBody),
    headers: {
      "Content-Type": "application/json",
    },
  })
  const { data } = await response.json()
  // commentDescriptions is hidden
  // @ts-ignore
  return printSchema(buildClientSchema(data), { commentDescriptions: true })
}

const downloadGitHubReaction = async release => {
  const response = await fetch(
    `https://github.com/artsy/reaction/raw/v${release}/data/schema.graphql`
  )

  const body = await response.text()
  return body
}

const getBreakingChanges = async (metaphysicsEnv) => {
  const packageJSON = JSON.parse(
    readFileSync(__dirname + "/../package.json", "utf8")
  )
  const reactionVersion = packageJSON["dependencies"]["@artsy/reaction"]
  const reactionSchema = await downloadGitHubReaction(reactionVersion)
  const metaphyicsSchema = await downloadMetaphysicsSchema(`https://metaphysics-${metaphysicsEnv}.artsy.net/`)
  return findBreakingChanges(
    buildSchema(reactionSchema),
    buildSchema(metaphyicsSchema)
  )
}

module.exports = {
  getBreakingChanges,
}

// @ts-ignore
if (require.main === module) {
  // When this is being called as a script via `node scripts/validate_schemas.js`
  if (process.argv.length != 3) {
    console.log('This script must be called with either "staging" or "production"')
    process.exitCode = 1
  } else {
    const env = process.argv[2]
    getBreakingChanges(env).then(changes => {
      if (changes.length) {
        process.exitCode = 1
        console.error(
          `Failing due to breaking changes between Force and Metaphysics ${env}\n\n`
        )
        console.error(changes)
        console.error(
          `\n\nYou should deploy metaphysics ${env}, and re-deploy force`
        )
      } else {
        console.log("No breaking changes found!")
      }
    })
  }
}

refactor scripts/validate_schemas.js to check reaction against metaphysics