#!/usr/bin/env -S nix shell nixpkgs#deno --command deno run --allow-read --allow-run --allow-net

import * as path from "https://deno.land/std@0.181.0/path/mod.ts";

// output the best guess URL for viewing the file at the current git revision in
// the git forge's web interface

// TODO: --help, -h menu

const file = Deno.args[0];

if (!file) {
  console.error("No file argument provided");
  Deno.exit(1);
}

async function cmdOutput(cmd: string[]) {
  return new TextDecoder().decode(
    await Deno.run({
      cmd: cmd,
      stdout: "piped",
    })
      .output(),
  ).trim();
}

type ForgeType = "gitlab" | "github" | "gitea";

function getForgeType(hostname: string): ForgeType {
  if (hostname == "git.lyte.dev") {
    return "gitea";
  } else if (hostname.endsWith("github.com")) {
    return "github";
  } else {
    return "gitlab";
  }
}

function getUrl(repoRoot: string, remote: string, commit: string) {
  try {
    // try http remote
    console.log(new URL(remote));
    throw new Error("HTTP(S) remotes not implemented");
  } catch {
    const hostname = remote.split("@").slice(-1)[0].split(":")[0];
    const forgeType = getForgeType(hostname);
    let repoPath = remote.split(":")[1];
    if (repoPath.endsWith(".git")) {
      repoPath = repoPath.slice(0, -4);
    }
    let fileRepoPath = path.resolve(file);
    if (fileRepoPath.startsWith(repoRoot)) {
      fileRepoPath = fileRepoPath.slice(repoRoot.length + 1); // for the trailing slash
    } else {
      throw new Error(`File ${fileRepoPath} is not in repo at ${repoRoot}`);
    }
    switch (forgeType) {
      case "gitlab":
        return `https://${hostname}/${repoPath}/-/blob/${commit}/${fileRepoPath}`;
      case "gitea":
        return `https://${hostname}/${repoPath}/src/commit/${commit}/${fileRepoPath}`;
      case "github":
        return `https://${hostname}/${repoPath}/blob/${commit}/${fileRepoPath}`;
    }
  }
}

// TODO: cd to dir
const repoRoot = await cmdOutput(["git", "rev-parse", "--show-toplevel"]);
const remote = await cmdOutput(["git", "remote", "get-url", "origin"]);
const commit = await cmdOutput(["git", "rev-parse", "HEAD"]);
const url = getUrl(repoRoot, remote, commit);
console.log(url);