const std = @import("std");
const Config = @import("../config.zig").Config;
const db = @import("../db.zig");
const core = @import("../core.zig");

pub fn run(allocator: std.mem.Allocator, args: []const []const u8) !void {
    var flags = core.flags.CommonFlags{};
    var remaining = try core.flags.parseCommon(allocator, args, &flags);
    defer remaining.deinit(allocator);

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

    // Handle help flag early
    if (flags.help) {
        return printUsage();
    }

    // Parse CLI-specific overrides and flags
    const cli_tracking_uri = core.flags.parseKVFlag(remaining.items, "tracking-uri");
    const cli_artifact_path = core.flags.parseKVFlag(remaining.items, "artifact-path");
    const cli_sync_uri = core.flags.parseKVFlag(remaining.items, "sync-uri");
    const force_local = core.flags.parseBoolFlag(remaining.items, "local");

    var cfg = try Config.loadWithOverrides(allocator, cli_tracking_uri, cli_artifact_path, cli_sync_uri);
    defer cfg.deinit(allocator);

    // Print resolved config
    std.debug.print("Resolved config:\n", .{});
    std.debug.print("\ttracking_uri  = {s}", .{cfg.tracking_uri});

    // Indicate if using default
    if (cli_tracking_uri == null and std.mem.eql(u8, cfg.tracking_uri, "sqlite://./fetch_ml.db")) {
        std.debug.print("\t(default)\n", .{});
    } else {
        std.debug.print("\n", .{});
    }

    std.debug.print("\tartifact_path = {s}", .{cfg.artifact_path});
    if (cli_artifact_path == null and std.mem.eql(u8, cfg.artifact_path, "./experiments/")) {
        std.debug.print("\t(default)\n", .{});
    } else {
        std.debug.print("\n", .{});
    }
    std.debug.print("\tsync_uri = {s}\n", .{if (cfg.sync_uri.len > 0) cfg.sync_uri else "(not set)"});
    std.debug.print("\n", .{});

    // Default path: create config only (no DB speculatively)
    if (!force_local) {
        std.debug.print("Created .fetchml/config.toml\n", .{});
        std.debug.print("\tLocal tracking DB will be created automatically if server becomes unavailable.\n", .{});

        if (cfg.sync_uri.len > 0) {
            std.debug.print("\tServer: {s}:{d}\n", .{ cfg.worker_host, cfg.worker_port });
        }
        return;
    }

    // --local path: create config + DB now
    std.debug.print("(local mode explicitly requested)\n\n", .{});

    // Get DB path from tracking URI
    const db_path = try cfg.getDBPath(allocator);
    defer allocator.free(db_path);

    // Check if DB already exists
    const db_exists = blk: {
        std.fs.accessAbsolute(db_path, .{}) catch |err| {
            if (err == error.FileNotFound) break :blk false;
        };
        break :blk true;
    };

    if (db_exists) {
        std.debug.print("Database already exists: {s}\n", .{db_path});
    } else {
        // Create parent directories if needed
        if (std.fs.path.dirname(db_path)) |dir| {
            std.fs.makeDirAbsolute(dir) catch |err| {
                if (err != error.PathAlreadyExists) {
                    std.log.err("Failed to create directory {s}: {}", .{ dir, err });
                    return error.MkdirFailed;
                }
            };
        }

        // Initialize database (creates schema)
        var database = try db.DB.init(allocator, db_path);
        defer database.close();
        defer database.checkpointOnExit();

        std.debug.print("Created database: {s}\n", .{db_path});
    }

    std.debug.print("Created .fetchml/config.toml\n", .{});
    std.debug.print("Schema applied (WAL mode enabled)\n", .{});
    std.debug.print("\tfetch_ml.db-wal and fetch_ml.db-shm will appear during use — expected.\n", .{});
    std.debug.print("\tThe DB is just a file. Delete it freely — recreated automatically on next run.\n", .{});
}

fn printUsage() void {
    std.debug.print("Usage: ml init [OPTIONS]\n\n", .{});
    std.debug.print("Initialize FetchML configuration\n\n", .{});
    std.debug.print("Options:\n", .{});
    std.debug.print("\t--local\t\t\tCreate local database now (default: config only)\n", .{});
    std.debug.print("\t--tracking-uri URI\tSQLite database path (e.g., sqlite://./fetch_ml.db)\n", .{});
    std.debug.print("\t--artifact-path PATH\tArtifacts directory (default: ./experiments/)\n", .{});
    std.debug.print("\t--sync-uri URI\t\tServer to sync with (e.g., wss://ml.company.com/ws)\n", .{});
    std.debug.print("\t-h, --help\t\tShow this help\n", .{});
}
