function getCleanUriPath(uri: string) {
  // Handle both URIs and plain paths
  let path: string
  try {
    const parsed = new URL(uri)
    path = parsed.pathname
  } catch {
    // Not a valid URL, treat as plain path
    path = uri
  }
  let clean = path.replace(/^\//, "") // remove start slash
  return clean.replace(/\/$/, "") // remove end slash
}

export function findUriInDirs(
  uri: string,
  dirUriCandidates: string[],
): {
  uri: string
  relativePathOrBasename: string
  foundInDir: string | null
} {
  const uriParsed = new URL(uri)
  const uriPathParts = getCleanUriPath(uri).split("/")

  for (const dir of dirUriCandidates) {
    const dirParsed = new URL(dir)

    if (uriParsed.protocol !== dirParsed.protocol) {
      continue
    }
    // Can't just use startsWith because e.g.
    // file:///folder/file is not within file:///fold

    // At this point we break the path up and check if each dir path part matches
    const dirPathParts = getCleanUriPath(dir).split("/")

    if (uriPathParts.length < dirPathParts.length) {
      continue
    }
    let allDirPartsMatch = true
    for (let i = 0; i < dirPathParts.length; i++) {
      if (dirPathParts[i] !== uriPathParts[i]) {
        allDirPartsMatch = false
      }
    }
    if (allDirPartsMatch) {
      const relativePath = uriPathParts.slice(dirPathParts.length).map(decodeURIComponent).join("/")
      return {
        uri,
        relativePathOrBasename: relativePath,
        foundInDir: dir,
      }
    }
  }
  // Not found
  return {
    uri,
    relativePathOrBasename: getUriPathBasename(uri),
    foundInDir: null,
  }
}

/*
  Returns just the file or folder name of a URI
*/
export function getUriPathBasename(uri: string): string {
  const path = getCleanUriPath(uri)
  const basename = path.split("/").pop() || ""
  return decodeURIComponent(basename)
}

function getFileExtensionFromBasename(basename: string) {
  const parts = basename.split(".")
  if (parts.length < 2) {
    return ""
  }
  return (parts.slice(-1)[0] ?? "").toLowerCase()
}

/*
  Returns the file extension of a URI
*/
export function getUriFileExtension(uri: string) {
  const baseName = getUriPathBasename(uri)
  return getFileExtensionFromBasename(baseName)
}

export function getLastNUriRelativePathParts(dirUriCandidates: string[], uri: string, n: number): string {
  const { relativePathOrBasename } = findUriInDirs(uri, dirUriCandidates)
  return getLastNPathParts(relativePathOrBasename, n)
}

export function getShortestUniqueRelativeUriPaths(
  uris: string[],
  dirUriCandidates: string[],
): {
  uri: string
  uniquePath: string
}[] {
  // Split all URIs into segments and count occurrences of each suffix combination
  const segmentCombinationsMap = new Map<string, number>()
  const segmentsInfo = uris.map((uri) => {
    const { relativePathOrBasename } = findUriInDirs(uri, dirUriCandidates)
    const segments = relativePathOrBasename.split("/")
    const suffixes: string[] = []

    // Generate all possible suffix combinations, starting from the shortest (basename)
    for (let i = segments.length - 1; i >= 0; i--) {
      const suffix = segments.slice(i).join("/")
      suffixes.push(suffix) // Now pushing in order from shortest to longest
      // Count occurrences of each suffix
      segmentCombinationsMap.set(suffix, (segmentCombinationsMap.get(suffix) || 0) + 1)
    }

    return { uri, segments, suffixes, relativePathOrBasename }
  })
  // Find shortest unique path for each URI
  return segmentsInfo.map(({ uri, suffixes, relativePathOrBasename }) => {
    // Since suffixes are now ordered from shortest to longest,
    // the first unique one we find will be the shortest
    const uniquePath = suffixes.find((suffix) => segmentCombinationsMap.get(suffix) === 1) ?? relativePathOrBasename // fallback to full path if no unique suffix found
    return { uri, uniquePath }
  })
}

// Only used when working with system paths and relative paths
// Since doesn't account for URI segements before workspace
function getLastNPathParts(filepath: string, n: number): string {
  if (n <= 0) {
    return ""
  }
  return filepath.split(/[\\/]/).slice(-n).join("/")
}
