#!/usr/bin/env bash
#
# This file will publish and build flakes that are on atproto

set -euo pipefail

check_command() {
    if ! command -v $1 >/dev/null 2>&1; then
        echo "Missing command $1"
        echo "Install it and try this again or alternatively, try building this through the flake."
        exit 1
    fi
}

check_command goat
check_command git
check_command jq

check_login() {
    if ! goat account check-auth >/dev/null 2>&1; then
        echo "Please make sure you have logged in before-hand. Try:"
        echo ""
        printf "\t%s\n" "goat account login -u your_username_here -p your_app_password_here"
        echo ""
        echo "If you don't want to supply your password on the command-line, use a CLI password manager like \`pass\`:"
        echo ""
        printf "\t%s\n" "pass insert atproto/nixat"
        printf "\t%s\n" "goat account login -u your_username_here -p \"\$(pass show atproto/nixat)\""
        exit 1
    fi
}

build() {
    local aturi="$1"
    shift
    echo "building flake pointed to by \`${aturi}\`:"
    check_login
    record="$(goat get "$aturi")"
    source="$(jq -r '.source' <<<"$record")"
    rev="$(jq -r '.rev' <<<"$record")"
    narHash="$(jq -r '.narHash' <<<"$record")"

    defaultFileContent="$(printf 'let src = builtins.fetchGit { url = "%s"; rev = "%s"; }; in assert src.narHash == "%s"; src.outPath' "$source" "$rev" "$narHash")"
    srcPath="$(nix eval --expr "$defaultFileContent" | sed -r 's/\"([^\"]+)\"/\1/')"
    nix build "$srcPath"
}

publish() {
    local path="$(realpath "$1")" version="$2"
    shift
    shift
    echo "publishing flake at ${path} with version ${version}"

    local rev source narHash publishedAt record
    rev="$(git -C "$path" rev-parse HEAD)"
    source="$(git -C "$path" remote get-url origin)"
    narHash="$(nix flake metadata --json "git+file://${path}?rev=${rev}" | jq -r .locked.narHash)"
    publishedAt="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

    record="$(printf '{"$type":"space.stau.nix.release","rev":"%s","source":"%s","narHash":"%s","publishedAt":"%s"}' "$rev" "$source" "$narHash" "$publishedAt")"
    jq -n "$record" | goat record create --rkey "$version" --no-validate -
}

usage() {
    echo "Usage: $0 <subcmd>"
    echo ""
    echo "The subcommands are:"
    echo ""
    printf "\t%s\n" "build <aturi>               build a flake pointed at by <aturi>"
    printf "\t%s\n" "publish <path> <version>    publish the flake at <path> with version <version>"
    printf "\t%s\n" "help | -h | --help | ?      show this help"
}

if [ $# -gt 0 ]; then
    case $1 in
        "build")
            if [ $# -gt 1 ]; then
                build "$2"
            else
                echo "expected an AT URI as an argument"
                usage
                exit 1
            fi
            ;;
        "publish")
            if [ $# -gt 2 ]; then
                publish "$2" "$3"
            else
                echo "expected a path and a version name as arguments"
                usage
                exit 1
            fi
            ;;
        "help"|"-h"|"--help"|"?")
            usage
            ;;
        *)
            usage
            exit 1
            ;;
    esac
else
    usage
    exit 1
fi
