import "./set-env"
// Import this first for Sentry to be initialized before other imports!
import "./instrument"

import express from "express"
import cors from "cors"
import { ghAppMiddleware, ghAppPathPrefix } from "./github/github-app"

import * as console from "console"
import { posthog } from "./analytics"
import { suggestPrChanges } from "./endpoints/suggest-pr-changes"
import { createPr } from "./endpoints/create-pr"
import { isGitHubAppInstalled } from "./endpoints/is-github-app-installed"
import { logRequestBody, logRequestDetails } from "./middlewares/logRequestDetails"
import { healthcheck } from "./endpoints/healthcheck"
import { collectEmail } from "./endpoints/collect-email"
import { checkForValidAPIKey } from "./middlewares/check-valid-api-key"
import { trackEndpointCalls } from "./middlewares/track-endpoint-calls"
import { verifyExistingOptimizations } from "./endpoints/verify-existing-optimizations"
import { getUser } from "./endpoints/cli-get-user"
import { addAsync } from "@awaitjs/express"
import * as Sentry from "@sentry/node"

const port = process.env.PORT ?? 3001

const appExpress = addAsync(express())

// The request handler must be the first middleware on the app
// appExpress.use(
//   Sentry.Handlers.requestHandler({ // arc: obsolete in sentry 8.x.x
//     request: ["userId"], //TODO attach the userid to sentry logs some other way
//   }),
// )

appExpress.use(logRequestDetails)

// Mount the github webhook middleware onto the express application
// MUST be mounted before express.json() middleware
console.log(`Mounting GitHub webhook middleware at path: ${ghAppPathPrefix}`)
appExpress.postAsync(`${ghAppPathPrefix}/webhooks`, async (req, res) => {
  const willHandle = await ghAppMiddleware(req, res)
  if (willHandle) {
    console.log(`GitHub App middleware will handle this request.`)
  }
})

// MUST be after github webhook middleware
appExpress.use(express.json({ limit: "10mb" }))

if (process.env.NODE_ENV !== "PRODUCTION") {
  // Allow all origins in development
  console.log("CORS: Allowing all origins in development.")
  appExpress.use(cors({ origin: "*" }))

  // Log request body for debugging purposes
  appExpress.use(logRequestBody)
}

appExpress.get("/", (req, res) => {
  return res.status(200).send("OK")
})

appExpress.get("/healthcheck", healthcheck)

appExpress.postAsync("/cfapi/collect-email", collectEmail)

// All endpoints defined after this will require a valid API key
// @ts-expect-error: TS2555
appExpress.useAsync(checkForValidAPIKey)

// Posthog tracks calls to all endpoints defined after this
appExpress.use(trackEndpointCalls)

appExpress.get("/cfapi/cli-get-user", getUser)

// Return the list of ALL repositories where Codeflash is installed
// Seems to not be used anywhere; scheduled for deletion by June 30, 2024
// appExpress.getAsync("/cfapi/installed_repositories", installedRepositories)

appExpress.postAsync("/cfapi/suggest-pr-changes", suggestPrChanges)

appExpress.postAsync("/cfapi/create-pr", createPr)

appExpress.getAsync("/cfapi/is-github-app-installed", isGitHubAppInstalled)

appExpress.postAsync("/cfapi/verify-existing-optimizations", verifyExistingOptimizations)

// The error handler must be registered before any other error middleware and after all controllers
Sentry.setupExpressErrorHandler(appExpress)

// Start the server
appExpress.listen(port, () => {
  console.log(
    `Server is listening on ${port} for CF API requests. Github App webhook events mounted at ${ghAppPathPrefix}`,
  )
  console.log("Press Ctrl + C to quit.")
})

posthog.shutdown()
