const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // public library module (the langref parser/renderer)
    const mod = b.addModule("zigman", .{
        .root_source_file = b.path("src/root.zig"),
        .target = target,
        .optimize = optimize,
    });

    const exe = b.addExecutable(.{
        .name = "zigman",
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/main.zig"),
            .target = target,
            .optimize = optimize,
            .imports = &.{.{ .name = "zigman", .module = mod }},
        }),
    });
    b.installArtifact(exe);

    const run = b.addRunArtifact(exe);
    run.step.dependOn(b.getInstallStep());
    if (b.args) |args| run.addArgs(args);
    b.step("run", "run zigman").dependOn(&run.step);

    const tests = b.addTest(.{ .root_module = mod });
    const run_tests = b.addRunArtifact(tests);
    b.step("test", "run unit tests").dependOn(&run_tests.step);

    // `zig build release --prefix www` cross-compiles every target into
    // www/release/<arch>-<os>/zigman and stages the install script + landing
    // page, ready to serve as a tangled Git site. Dir names match `uname`
    // output so web/install.sh can resolve the right binary.
    const release = b.step("release", "cross-compile distributable binaries into the site dir");
    const Target = struct { query: []const u8, dir: []const u8 };
    const targets = [_]Target{
        .{ .query = "aarch64-macos", .dir = "aarch64-macos" },
        .{ .query = "x86_64-macos", .dir = "x86_64-macos" },
        .{ .query = "aarch64-linux-musl", .dir = "aarch64-linux" },
        .{ .query = "x86_64-linux-musl", .dir = "x86_64-linux" },
    };
    const mk = b.addSystemCommand(&.{ "mkdir", "-p", "www/release" });
    for (targets) |t| {
        const q = std.Target.Query.parse(.{ .arch_os_abi = t.query }) catch unreachable;
        const rt = b.resolveTargetQuery(q);
        const lib = b.createModule(.{
            .root_source_file = b.path("src/root.zig"),
            .target = rt,
            .optimize = .ReleaseSafe,
            .strip = true,
        });
        const rexe = b.addExecutable(.{
            .name = "zigman",
            .root_module = b.createModule(.{
                .root_source_file = b.path("src/main.zig"),
                .target = rt,
                .optimize = .ReleaseSafe,
                .strip = true,
                .imports = &.{.{ .name = "zigman", .module = lib }},
            }),
        });
        // stage the binary under zig-out, then gzip it into the served www tree.
        // an extensionless file under a sub-path is treated as a directory by the
        // static host, so binaries are distributed as per-target tarballs.
        const inst = b.addInstallArtifact(rexe, .{
            .dest_dir = .{ .override = .{ .custom = b.fmt("release/{s}", .{t.dir}) } },
        });
        const tar = b.addSystemCommand(&.{
            "tar",                                     "-czf",
            b.fmt("www/release/{s}.tar.gz", .{t.dir}), "-C",
            b.fmt("zig-out/release/{s}", .{t.dir}),    "zigman",
        });
        tar.step.dependOn(&inst.step);
        tar.step.dependOn(&mk.step);
        release.dependOn(&tar.step);
    }
    // install.sh sits alongside the tarballs
    const cp = b.addSystemCommand(&.{ "cp", "web/install.sh", "www/" });
    cp.step.dependOn(&mk.step);
    release.dependOn(&cp.step);

    const cp_assets = b.addSystemCommand(&.{ "cp", "web/site.css", "web/nav.js", "web/llms.txt", "web/prompt.md", "www/" });
    cp_assets.step.dependOn(&mk.step);
    release.dependOn(&cp_assets.step);

    const cp_skill = b.addSystemCommand(&.{ "cp", "skills/zigman/SKILL.md", "www/skill.md" });
    cp_skill.step.dependOn(&mk.step);
    release.dependOn(&cp_skill.step);

    // the landing page is hand-designed; keep release output in sync with the
    // source under web/ without regenerating it from README.md.
    const cp_index = b.addSystemCommand(&.{ "cp", "web/index.html", "www/index.html" });
    cp_index.step.dependOn(&mk.step);
    release.dependOn(&cp_index.step);

    // the in-depth practical guide, rendered from markdown
    const md2html = b.addExecutable(.{
        .name = "md2html",
        .root_module = b.createModule(.{
            .root_source_file = b.path("tools/md2html.zig"),
            .target = b.graph.host,
            .optimize = .Debug,
        }),
    });
    const gen_guide = b.addRunArtifact(md2html);
    gen_guide.addFileArg(b.path("docs/guide.md"));
    gen_guide.addArg("www/guide.html");
    gen_guide.step.dependOn(&mk.step);
    release.dependOn(&gen_guide.step);
}
