import type { FileDiffContent, Hunk } from "@codeflash-ai/code-suggester/build/src/types.js"

import {
  getRawSuggestionHunks,
  partitionSuggestedHunksByScope,
} from "@codeflash-ai/code-suggester/build/src/utils/hunk-utils.js"
import { getPullRequestHunks } from "@codeflash-ai/code-suggester/build/src/github/review-pull-request.js"
import type { Octokit } from "@octokit/rest"

export function fileDiffsToMap(obj: Record<string, FileDiffContent>): Map<string, FileDiffContent> {
  const map = new Map()
  Object.keys(obj).forEach(key => {
    if (
      obj[key] &&
      typeof obj[key] === "object" &&
      typeof obj[key].oldContent === "string" &&
      typeof obj[key].newContent === "string"
    ) {
      map.set(key, {
        oldContent: obj[key].oldContent,
        newContent: obj[key].newContent,
      } as FileDiffContent)
    }
  })
  return map
}

export async function determineValidHunks(
  octokit: Octokit,
  remote: { owner: string; repo: string },
  pullNumber: number,
  pageSize: number,
  diffContents: Map<string, FileDiffContent>,
) {
  // get the hunks from the pull request
  const pullRequestHunks = await getPullRequestHunks(octokit as any, remote, pullNumber, pageSize)
  // get the hunks from the suggested change
  const allSuggestedHunks: Map<string, Hunk[]> = getRawSuggestionHunks(diffContents)
  // split hunks by commentable and uncommentable
  const { validHunks, invalidHunks } = partitionSuggestedHunksByScope(
    pullRequestHunks,
    allSuggestedHunks,
  )

  return { validHunks, invalidHunks }
}

export function isDiffContentsWellFormed(
  diffContents: any,
): diffContents is Record<string, FileDiffContent> {
  return Object.values(diffContents).every(
    content =>
      content !== null &&
      typeof content === "object" &&
      "oldContent" in content &&
      "newContent" in content &&
      typeof content.oldContent === "string" &&
      typeof content.newContent === "string",
  )
}
