import { type App, type Octokit } from "octokit"

// Checks if the user is a collaborator on the repository
export async function isUserCollaborator(
  installationOctokit: Octokit,
  owner: string,
  repo: string,
  nickname: string,
): Promise<boolean> {
  try {
    const response = await installationOctokit.rest.repos.checkCollaborator({
      owner,
      repo,
      username: nickname,
    })
    // If the request is successful, the user is a collaborator and we can continue
    return response.status === 204
  } catch (error: any) {
    if (error.status === 404) {
      return false // User is not a collaborator
    }
    // Handle other potential errors
    throw error // Rethrow error for upstream handling
  }
}

export async function getInstallationOctokitByOwner(
  githubApp: App,
  owner: string,
  repo: string,
): Promise<Octokit | Error> {
  try {
    const repoInstallation = await githubApp.octokit.rest.apps.getRepoInstallation({
      owner,
      repo,
    })
    const installationId = repoInstallation.data.id
    return await githubApp.getInstallationOctokit(installationId)
  } catch (error: any) {
    console.error(`Error getting installation Octokit for ${owner}/${repo}:`, error)
    if (error.status === 404) {
      return Error(`GitHub App is not installed on the repository ${owner}/${repo}`)
    } else {
      return Error(`Error checking GitHub App installation status for repo ${owner}/${repo}`)
    }
  }
}

// Ensures that a label exists on a repository, creating it if it doesn't
async function ensureLabelExists(
  installationOctokit: Octokit,
  owner: string,
  repo: string,
  labelName: string,
  color: string,
  description: string,
): Promise<void> {
  try {
    await installationOctokit.rest.issues.getLabel({
      owner,
      repo,
      name: labelName,
    })
  } catch (error: any) {
    if (error.status === 404) {
      // Label does not exist, create it
      await installationOctokit.rest.issues.createLabel({
        owner,
        repo,
        name: labelName,
        color,
        description,
      })
    } else {
      // An error occurred that wasn't a 404, rethrow it
      throw error
    }
  }
}

// Adds a label to a pull request, creating the label if it doesn't exist
export async function addLabelToPullRequest(
  installationOctokit: Octokit,
  owner: string,
  repo: string,
  pullNumber: number,
  labelName: string = "⚡️ codeflash",
  labelColor: string = "FFC043",
  description: string = "Optimization PR opened by Codeflash AI",
): Promise<void> {
  await ensureLabelExists(installationOctokit, owner, repo, labelName, labelColor, description)

  await installationOctokit.rest.issues.addLabels({
    owner,
    repo,
    issue_number: pullNumber,
    labels: [labelName],
  })
}

export function buildPrTitle(functionName: string, speedupPct: string): string {
  const type = functionName.includes(".") ? "method" : "function"
  return `⚡️ Speed up ${type} \`${functionName}\` by ${speedupPct}`
}

export function buildDependentPrTitle(
  functionName: string,
  speedupPct: string,
  pullNumber: number,
  baseBranch: string,
): string {
  return buildPrTitle(functionName, speedupPct) + ` in PR #${pullNumber} (\`${baseBranch}\`)`
}
