const std = @import("std");
const config = @import("../config.zig");
const crypto = @import("../utils/crypto.zig");
const rsync = @import("../utils/rsync_embedded.zig");
const ws = @import("../net/ws/client.zig");
const core = @import("../core.zig");
const mode = @import("../mode.zig");

pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void {
    var flags = core.flags.CommonFlags{};
    var should_sync = false;
    const sync_interval: u64 = 30; // Default 30 seconds

    if (args.len == 0) {
        return printUsage();
    }

    // Parse flags
    for (args) |arg| {
        if (std.mem.eql(u8, arg, "--help") or std.mem.eql(u8, arg, "-h")) {
            return printUsage();
        } else if (std.mem.eql(u8, arg, "--sync")) {
            should_sync = true;
        } else if (std.mem.eql(u8, arg, "--json")) {
            flags.json = true;
        }
    }

    core.output.setMode(if (flags.json) .json else .text);

    const cfg = try config.Config.load(allocator);
    defer {
        var mut_cfg = cfg;
        mut_cfg.deinit(allocator);
    }

    // Check mode if syncing
    if (should_sync) {
        const mode_result = try mode.detect(allocator, cfg);
        if (mode.isOffline(mode_result.mode)) {
            std.debug.print("ml watch --sync requires server connection\n", .{});
            return error.RequiresServer;
        }
    }

    if (flags.json) {
        std.debug.print("{{\"ok\":true,\"action\":\"watch\",\"sync\":{s}}}\n", .{if (should_sync) "true" else "false"});
    } else {
        if (should_sync) {
            std.debug.print("Watching for changes with auto-sync every {d}s...\n", .{sync_interval});
        } else {
            std.debug.print("Watching directory for changes...\n", .{});
        }
        std.debug.print("Press Ctrl+C to stop\n", .{});
    }

    // Watch loop
    var last_synced: i64 = 0;
    while (true) {
        if (should_sync) {
            const now = std.time.timestamp();
            if (now - last_synced >= @as(i64, @intCast(sync_interval))) {
                // Trigger sync
                const sync_cmd = @import("sync.zig");
                sync_cmd.run(allocator, &[_][]const u8{"--json"}) catch |err| {
                    if (!flags.json) {
                        std.debug.print("Auto-sync failed: {}\n", .{err});
                    }
                };
                last_synced = now;
            }
        }

        // Wait before checking again
        std.Thread.sleep(2_000_000_000); // 2 seconds
    }
}

fn syncAndQueue(allocator: std.mem.Allocator, path: []const u8, job_name: ?[]const u8, priority: u8, should_queue: bool, cfg: config.Config) ![]u8 {
    // Calculate commit ID
    const commit_id = try crypto.hashDirectory(allocator, path);

    // Sync files via rsync
    const remote_path = try std.fmt.allocPrint(
        allocator,
        "{s}@{s}:{s}/{s}/files/",
        .{ cfg.worker_user, cfg.worker_host, cfg.worker_base, commit_id },
    );
    defer allocator.free(remote_path);

    try rsync.sync(allocator, path, remote_path, cfg.worker_port);

    if (should_queue) {
        const actual_job_name = job_name orelse commit_id[0..8];
        const api_key_hash = try crypto.hashApiKey(allocator, cfg.api_key);
        defer allocator.free(api_key_hash);

        // Connect to WebSocket and queue job
        const ws_url = try cfg.getWebSocketUrl(allocator);
        defer allocator.free(ws_url);

        var client = try ws.Client.connect(allocator, ws_url, cfg.api_key);
        defer client.close();

        try client.sendQueueJob(actual_job_name, commit_id, priority, api_key_hash);

        const response = try client.receiveMessage(allocator);
        defer allocator.free(response);

        if (response.len > 0 and response[0] == 0x00) {
            std.debug.print("Job queued successfully: {s}\n", .{actual_job_name});
        }
    }

    return commit_id;
}

fn printUsage() void {
    std.debug.print("Usage: ml watch [options]\n\n", .{});
    std.debug.print("Watch for changes and optionally auto-sync.\n\n", .{});
    std.debug.print("Options:\n", .{});
    std.debug.print("\t--sync\t\tAuto-sync runs to server every 30s\n", .{});
    std.debug.print("\t--json\t\tOutput structured JSON\n", .{});
    std.debug.print("\t--help, -h\tShow this help message\n", .{});
}
