//
// Persisted state. Stored at ~/.config/player/config.json on Linux,
// ~/Library/Application Support/player/config.json on macOS.
//
// We persist:
// - server URL / username / auth token / user id (so subsequent launches
//   skip the login screen entirely)
// - device_id: a stable per-install id. Jellyfin permits only one active
//   token per DeviceId, so re-using a hardcoded constant means any second
//   instance silently revokes the first instance's saved token.
// - master volume (so the user doesn't have to re-set it every time)
//
// Password is never persisted.
//

Persisted_Config :: struct {
    server_url:    string;
    username:      string;
    auth_token:    string;
    user_id:       string;
    device_id:     string;
    master_volume: float = 1.0;
}

config_path :: () -> string {
    home, ok := get_home_directory();
    if !ok  return "";
    #if OS == .MACOS {
        return tprint("%/Library/Application Support/player/config.json", home);
    } else {
        return tprint("%/.config/player/config.json", home);
    }
}

config_save :: () {
    p := config_path();
    if !p  return;

    cfg: Persisted_Config;
    cfg.server_url    = app.jellyfin.server_url;
    cfg.username      = app.jellyfin.username;
    cfg.auth_token    = app.jellyfin.auth_token;
    cfg.user_id       = app.jellyfin.user_id;
    cfg.device_id     = app.jellyfin.device_id;
    cfg.master_volume = app.master_volume;

    json := Jaison.json_write_string(cfg);
    defer free(json);

    dir := path_strip_filename(p);
    make_directory_if_it_does_not_exist(dir, recursive=true);

    if !write_entire_file(p, json) {
        log_error("config_save: failed to write %", p);
        return;
    }
}

config_load :: () -> bool {
    p := config_path();
    if !p  return false;
    if !file_exists(p)  return false;
    contents, ok := read_entire_file(p, log_errors=false);
    if !ok  return false;
    defer free(contents);

    parse_ok, cfg := Jaison.json_parse_string(contents, Persisted_Config);
    if !parse_ok {
        log_warn("config_load: failed to parse %", p);
        return false;
    }

    app.jellyfin.server_url = copy_string(cfg.server_url);
    app.jellyfin.username   = copy_string(cfg.username);
    app.jellyfin.auth_token = copy_string(cfg.auth_token);
    app.jellyfin.user_id    = copy_string(cfg.user_id);
    app.jellyfin.device_id  = copy_string(cfg.device_id);

    if cfg.master_volume > 0  app.master_volume = clamp(cfg.master_volume, 0, 1);

    if cfg.auth_token.count > 0 && cfg.user_id.count > 0 {
        app.jellyfin.logged_in = true;
        log_info("loaded saved login (user_id=%)", cfg.user_id);
        return true;
    }
    return false;
}

// Ensure we have a stable device_id. Called after config_load so first-run
// installs (or pre-device_id configs migrating in) get one and persist it.
ensure_device_id :: () {
    if app.jellyfin.device_id.count > 0  return;
    app.jellyfin.device_id = generate_device_id();
    log_info("auth: generated new device_id");
    config_save();
}

config_clear :: () {
    p := config_path();
    if !p  return;
    file_delete(p);
}

#scope_file

generate_device_id :: () -> string {
    builder: String_Builder;
    for 0..15 {
        b := random_get() & 0xff;
        print_to_builder(*builder, "%", formatInt(b, base=16, minimum_digits=2));
    }
    return builder_to_string(*builder);
}
