#!/usr/bin/env -S deno run -RWN --allow-run=deno
// Copyright 2018-2025 the Deno authors. MIT license.

// deno-lint-ignore-file no-console

import { fileURLToPath } from "node:url";

/**
 * Trims the minimum indent from each line of a multiline string,
 * removing leading and trailing blank lines.
 * @param text
 * @returns the trimmed string
 */
export function trimIndent(text: string): string {
  if (text.startsWith("\n")) {
    text = text.slice(1);
  }
  const lines = text.split("\n");
  const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
  const indent = nonEmptyLines.length > 0
    ? Math.min(
      ...nonEmptyLines.map((line) => line.length - line.trimStart().length),
    )
    : 0;

  return lines
    .map((line) => {
      if (line.length <= indent) {
        return line.replace(/^ +/, "");
      } else {
        return line.slice(indent);
      }
    })
    .join("\n");
}

export function unindent(strings: TemplateStringsArray, ...values: unknown[]) {
  // normal template substitution
  const raw = String.raw({ raw: strings }, ...values);
  return trimIndent(raw);
}

const repo = "denoland/typescript-go";

interface GitHubRelease {
  "tag_name": string;
  assets: GitHubAsset[];
}

interface GitHubAsset {
  name: string;
  digest: string; // sha256:...
}

const latestResponse = await fetch(
  `https://api.github.com/repos/${repo}/releases/latest`,
);
if (!latestResponse.ok) {
  throw new Error(
    `Failed to fetch latest release: ${latestResponse.statusText}`,
  );
}
const latest = await latestResponse.json() as GitHubRelease;

const version = latest.tag_name;

const versionNoV = version.replace(/^v/, "");

const file = fileURLToPath(import.meta.resolve(
  "../cli/tsc/go/tsgo_version.rs",
));

const content = await Deno.readTextFile(file);
const match = content.match(/const VERSION: &str = "([^"]+)"/);
let currentVersion = "";
if (!match) {
  currentVersion = "";
} else {
  currentVersion = match[1];
}
console.log("Current version: ", currentVersion);
if (currentVersion === versionNoV) {
  console.log("Version is up to date, updating generated code");
} else {
  console.log("Updating version to: ", versionNoV);
}

function findHashes(
  release: GitHubRelease,
): {
  windowsX64: string;
  macosX64: string;
  macosArm64: string;
  linuxX64: string;
  linuxArm64: string;
} {
  const hashes = {
    windowsX64: "",
    macosX64: "",
    macosArm64: "",
    linuxX64: "",
    linuxArm64: "",
  };
  for (const asset of release.assets) {
    const parts = asset.name.split("-");
    const os = parts[parts.length - 2];
    const archAndExtension = parts[parts.length - 1];
    const arch = archAndExtension.split(".")[0];
    if (os === "windows" && arch === "x64") {
      hashes.windowsX64 = asset.digest;
    } else if (os === "macos" && arch === "x64") {
      hashes.macosX64 = asset.digest;
    } else if (os === "macos" && arch === "arm64") {
      hashes.macosArm64 = asset.digest;
    } else if (os === "linux" && arch === "x64") {
      hashes.linuxX64 = asset.digest;
    } else if (os === "linux" && arch === "arm64") {
      hashes.linuxArm64 = asset.digest;
    }
  }
  return hashes;
}

const hashes = findHashes(latest);
for (const [platform, hash] of Object.entries(hashes)) {
  if (!hash) {
    console.error(`No hashes found for ${platform}`);
    Deno.exit(1);
  }
}
const newContent = unindent`
  // Copyright 2018-2025 the Deno authors. MIT license.

  // This file is auto-generated by tools/update_tsgo.ts
  // DO NOT EDIT THIS FILE MANUALLY

  pub struct Hashes {
    pub windows_x64: &'static str,
    pub macos_x64: &'static str,
    pub macos_arm64: &'static str,
    pub linux_x64: &'static str,
    pub linux_arm64: &'static str,
  }
  
  impl Hashes {
    pub const fn all(&self) -> [&'static str; 5] {
      [
        self.windows_x64,
        self.macos_x64,
        self.macos_arm64,
        self.linux_x64,
        self.linux_arm64,
      ]
    }
  }

  pub const VERSION: &str = "${versionNoV}";
  pub const DOWNLOAD_BASE_URL: &str = 
    "https://github.com/${repo}/releases/download/${version}";
  pub const HASHES: Hashes = Hashes {
    windows_x64: "${hashes.windowsX64}",
    macos_x64: "${hashes.macosX64}",
    macos_arm64: "${hashes.macosArm64}",
    linux_x64: "${hashes.linuxX64}",
    linux_arm64: "${hashes.linuxArm64}",
  };
  
  const _: () = {
    let sha256 = "sha256".as_bytes();

    let mut i = 0;
    let hashes = HASHES.all();

    while i < hashes.len() {
      let hash = hashes[i].as_bytes();
      let mut j = 0;

      while j < 6 {
        if hash[j] != sha256[j] {
          panic!("Hash algorithm is not sha256");
        }
        j += 1;
      }
      i += 1;
    }
  };
`;

await Deno.writeTextFile(file, newContent);

if (currentVersion !== versionNoV) {
  console.log("Version updated to ", versionNoV);
}

await import("./format.js");
