#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/shell/shell.h>
#include <zephyr/sys/reboot.h>
#include <zephyr/settings/settings.h>
#include <string.h>
#include <stdlib.h>
#include <lasertag_utils.h>

LOG_MODULE_REGISTER(lasertag_utils, CONFIG_LASERTAG_UTILS_LOG_LEVEL);

/* Default values */
static char device_name[32] = "UnknownDevice";
static uint16_t thread_pan_id = 0xabcd;
static char thread_network_name[17] = "OpenThread-nRF";

/* --- Settings Handling (Persistent Storage) --- */

static int lasertag_settings_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg)
{
    const char *next;

    if (settings_name_steq(name, "name", &next) && !next) {
        if (len > sizeof(device_name) - 1) return -EINVAL;
        ssize_t rc = read_cb(cb_arg, device_name, len);
        if (rc >= 0) {
            device_name[rc] = '\0';
            return 0;
        }
        return (int)rc;
    }

    if (settings_name_steq(name, "pan_id", &next) && !next) {
        return read_cb(cb_arg, &thread_pan_id, sizeof(thread_pan_id)) >= 0 ? 0 : -EIO;
    }

    if (settings_name_steq(name, "net_name", &next) && !next) {
        if (len > sizeof(thread_network_name) - 1) return -EINVAL;
        ssize_t rc = read_cb(cb_arg, thread_network_name, len);
        if (rc >= 0) {
            thread_network_name[rc] = '\0';
            return 0;
        }
        return (int)rc;
    }

    return -ENOENT;
}

struct settings_handler lasertag_conf = {
    .name = "lasertag",
    .h_set = lasertag_settings_set
};

void lasertag_utils_init(void)
{
    LOG_INF("==========================================");
    LOG_INF("Lasertag System - Common Lib v0.0.1");
    
    int rc = settings_subsys_init();
    if (rc) {
        LOG_ERR("Settings subsys init failed (err %d)", rc);
    }

    settings_register(&lasertag_conf);
    settings_load();

    LOG_INF("Device Name : %s", device_name);
    LOG_INF("Thread PAN  : 0x%04x", thread_pan_id);
    LOG_INF("Thread Name : %s", thread_network_name);
    LOG_INF("==========================================");
}

const char* lasertag_get_device_name(void) { return device_name; }
uint16_t lasertag_get_thread_pan_id(void) { return thread_pan_id; }
const char* lasertag_get_thread_network_name(void) { return thread_network_name; }

/* --- Shell Commands --- */

#if CONFIG_LASERTAG_SHELL

static int cmd_name_set(const struct shell *sh, size_t argc, char **argv)
{
    strncpy(device_name, argv[1], sizeof(device_name) - 1);
    device_name[sizeof(device_name) - 1] = '\0';
    settings_save_one("lasertag/name", device_name, strlen(device_name));
    shell_print(sh, "Device name saved: %s", device_name);
    return 0;
}

static int cmd_thread_set_panid(const struct shell *sh, size_t argc, char **argv)
{
    thread_pan_id = (uint16_t)strtoul(argv[1], NULL, 0);
    settings_save_one("lasertag/pan_id", &thread_pan_id, sizeof(thread_pan_id));
    shell_print(sh, "Thread PAN ID saved: 0x%04x", thread_pan_id);
    return 0;
}

static int cmd_thread_set_name(const struct shell *sh, size_t argc, char **argv)
{
    strncpy(thread_network_name, argv[1], sizeof(thread_network_name) - 1);
    thread_network_name[sizeof(thread_network_name) - 1] = '\0';
    settings_save_one("lasertag/net_name", thread_network_name, strlen(thread_network_name));
    shell_print(sh, "Thread Network Name saved: %s", thread_network_name);
    return 0;
}

/* Subcommands for 'lasertag thread' */
SHELL_STATIC_SUBCMD_SET_CREATE(sub_thread,
    SHELL_CMD_ARG(panid, NULL, "Set PAN ID <id>", cmd_thread_set_panid, 2, 0),
    SHELL_CMD_ARG(name, NULL, "Set Network Name <name>", cmd_thread_set_name, 2, 0),
    SHELL_SUBCMD_SET_END
);

/* Main command 'lasertag' */
SHELL_STATIC_SUBCMD_SET_CREATE(sub_lasertag,
    SHELL_CMD_ARG(name, NULL, "Set device name <name>", cmd_name_set, 2, 0),
    SHELL_CMD(thread, &sub_thread, "Thread network configuration", NULL),
    SHELL_SUBCMD_SET_END
);

SHELL_CMD_REGISTER(lasertag, &sub_lasertag, "Lasertag control commands", NULL);

#endif /* CONFIG_LASERTAG_SHELL */