import * as core from "@actions/core"
import { Provider } from "@/provider/provider"

export function normalizeRunEnv() {
  const { providerID, modelID } = normalizeModel()
  return {
    providerID,
    modelID,
    runId: normalizeRunId(),
    share: normalizeShare(),
    oidcBaseUrl: normalizeOidcBaseUrl(),
    useGithubToken: normalizeUseGithubToken(),
  }
}

export function normalizeModel() {
  const value = process.env["MODEL"]
  if (!value) throw new Error(`Environment variable "MODEL" is not set`)
  const { providerID, modelID } = Provider.parseModel(value)
  if (!providerID.length || !modelID.length)
    throw new Error(`Invalid model ${value}. Model must be in the format "provider/model".`)
  return { providerID, modelID }
}

export function normalizeRunId() {
  const value = process.env["GITHUB_RUN_ID"]
  if (!value) throw new Error(`Environment variable "GITHUB_RUN_ID" is not set`)
  return value
}

export function normalizeShare(): boolean | undefined {
  const value = process.env["SHARE"]
  if (!value) return undefined
  if (value === "true") return true
  if (value === "false") return false
  throw new Error(`Invalid share value: ${value}. Share must be a boolean.`)
}

export function normalizeUseGithubToken() {
  const value = process.env["USE_GITHUB_TOKEN"]
  if (!value) return false
  if (value === "true") return true
  if (value === "false") return false
  throw new Error(`Invalid use_github_token value: ${value}. Must be a boolean.`)
}

export function normalizeOidcBaseUrl(): string {
  const value = process.env["OIDC_BASE_URL"]
  if (!value) return "https://api.saeeol.ai"
  return value.replace(/\/+$/, "")
}

export async function getOidcToken() {
  try {
    return await core.getIDToken("saeeol-github-action")
  } catch (error) {
    console.error("Failed to get OIDC token:", error instanceof Error ? error.message : error)
    throw new Error(
      "Could not fetch an OIDC token. Make sure to add `id-token: write` to your workflow permissions.",
      { cause: error },
    )
  }
}

export async function exchangeForAppToken(token: string, oidcBaseUrl: string, owner: string, repo: string) {
  const response = token.startsWith("github_pat_")
    ? await fetch(`${oidcBaseUrl}/api/integrations/github/exchange-token-with-pat`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ owner, repo }),
      })
    : await fetch(`${oidcBaseUrl}/api/integrations/github/exchange-token`, {
        method: "POST",
        headers: {
          Authorization: `Bearer ${token}`,
        },
      })

  if (!response.ok) {
    const responseJson = (await response.json()) as { error?: string }
    throw new Error(
      `App token exchange failed: ${response.status} ${response.statusText} - ${responseJson.error}`,
    )
  }

  const responseJson = (await response.json()) as { token: string }
  return responseJson.token
}

export async function revokeAppToken(appToken: string) {
  if (!appToken) return

  await fetch("https://api.github.com/installation/token", {
    method: "DELETE",
    headers: {
      Authorization: `Bearer ${appToken}`,
      Accept: "application/vnd.github+json",
      "X-GitHub-Api-Version": "2022-11-28",
    },
  })
}
