const std = @import("std");

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

    // ============================================================================
    // MODULES
    // ============================================================================

    // Main module (uses standard optimize option)
    const root_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // Debug module (always Debug optimization)
    const debug_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = .Debug,
    });

    // Release module (always ReleaseFast optimization)
    const release_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = .ReleaseFast,
    });

    // Test module (uses standard optimize option)
    const test_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // ============================================================================
    // EXECUTABLES
    // ============================================================================

    // Main executable
    const exe = b.addExecutable(.{
        .name = "manwhere",
        .root_module = root_module,
    });
    b.installArtifact(exe);

    // Debug executable
    const debug_exe = b.addExecutable(.{
        .name = "manwhere-debug",
        .root_module = debug_module,
    });

    // Release executable
    const release_exe = b.addExecutable(.{
        .name = "manwhere",
        .root_module = release_module,
    });

    // Check executable (for compilation check)
    const check_exe = b.addExecutable(.{
        .name = "check-compile",
        .root_module = root_module,
    });

    // Test executable
    const unit_tests = b.addTest(.{
        .root_module = test_module,
    });

    // ============================================================================
    // BUILD STEPS
    // ============================================================================

    // Default run step
    const run_cmd = b.addRunArtifact(exe);
    if (b.args) |args| run_cmd.addArgs(args);
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);

    // Debug build step
    const debug_step = b.step("debug", "Build with Debug optimization");
    b.installArtifact(debug_exe);
    debug_step.dependOn(b.getInstallStep());

    // Debug run step
    const debug_run_cmd = b.addRunArtifact(debug_exe);
    if (b.args) |args| debug_run_cmd.addArgs(args);
    debug_run_cmd.step.dependOn(&debug_exe.step);
    const debug_run_step = b.step("debug-run", "Run the app with Debug optimization");
    debug_run_step.dependOn(&debug_run_cmd.step);

    // Release step - build optimized binary and install to ~/.local/bin
    const release_step = b.step("release", "Build optimized binary and install to ~/.local/bin/");

    // Get home directory from environment
    const home = std.process.getEnvVarOwned(b.allocator, "HOME") catch {
        std.debug.print("Error: HOME environment variable not set\n", .{});
        return;
    };
    defer b.allocator.free(home);

    const install_path = std.fs.path.join(b.allocator, &.{ home, ".local", "bin" }) catch {
        std.debug.print("Error: Failed to construct install path\n", .{});
        return;
    };
    defer b.allocator.free(install_path);

    const install_exe = b.addInstallArtifact(release_exe, .{
        .dest_dir = .{ .override = .{ .custom = install_path } },
    });
    release_step.dependOn(&install_exe.step);

    // Test step - run all unit tests
    const run_unit_tests = b.addRunArtifact(unit_tests);
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_unit_tests.step);

    // Check step - compilation check without output
    const check_step = b.step("check", "Check code formatting and compilation");
    check_step.dependOn(&check_exe.step);

    // Format step - format source code
    const fmt_step = b.step("fmt", "Format source code");
    const fmt_cmd = b.addFmt(.{
        .paths = &.{ "src", "build.zig" },
        .check = false,
    });
    fmt_step.dependOn(&fmt_cmd.step);

    // Clean step - remove build artifacts
    const clean_step = b.step("clean", "Remove build artifacts");
    const clean_cmd = b.addSystemCommand(&.{
        "rm", "-rf", ".zig-cache", "zig-out",
    });
    clean_step.dependOn(&clean_cmd.step);
}
