import Foundation
import PackagePlugin

/// A prebuild plugin that stamps the commit the package is being built from into a
/// generated `GitCommit.swift`, compiled into the app. Because it's resolved during
/// the build (not at runtime), the hash is baked into the binary — so it's correct
/// even for a TestFlight / App Store archive built on CI, where the source tree and
/// git aren't present at runtime. Runs before every build, so the value stays fresh.
@main
struct EmbedGitCommit: BuildToolPlugin {
    func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
        let outputDir = context.pluginWorkDirectoryURL.appending(path: "GitCommit")
        let outputFile = outputDir.appending(path: "GitCommit.swift")
        let repoDir = context.package.directoryURL.path

        // `git -C` transparently resolves linked worktrees, so this works whether the
        // package is the main checkout or a worktree. On failure (no git / no repo, as
        // in some CI checkouts) the hash falls back to "unknown" and the app uses the
        // bundle version instead. A trailing "+" marks an uncommitted working tree.
        let script = """
        set -e
        mkdir -p "\(outputDir.path)"
        hash=$(git -C "\(repoDir)" rev-parse --short HEAD 2>/dev/null || echo unknown)
        if [ "$hash" != "unknown" ] && [ -n "$(git -C "\(repoDir)" status --porcelain 2>/dev/null)" ]; then
          hash="${hash}+"
        fi
        printf 'enum GitCommit { static let hash = "%s" }\\n' "$hash" > "\(outputFile.path)"
        """

        return [
            .prebuildCommand(
                displayName: "Embed git commit hash",
                executable: URL(fileURLWithPath: "/bin/sh"),
                arguments: ["-c", script],
                outputFilesDirectory: outputDir
            )
        ]
    }
}
