#include "led.h"
#include "zbus_message.h"

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/zbus/zbus.h>

LOG_MODULE_REGISTER(led);

#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)

static const struct gpio_dt_spec led0_gpio = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led1_gpio = GPIO_DT_SPEC_GET(LED1_NODE, gpios);

static bool led0_state = false;
static bool led1_state = false;

/* ZBUS handler - update LED state */
static void leds_zbus_handler(const struct zbus_channel *chan)
{
	const struct leds_message *msg;
	int ret;
	const struct gpio_dt_spec *target_gpio;
	bool *target_state;

	msg = zbus_chan_const_msg(chan);
	if (msg == NULL) {
		return;
	}

	if (msg->led_id == 0) {
		target_gpio = &led0_gpio;
		target_state = &led0_state;
	} else if (msg->led_id == 1) {
		target_gpio = &led1_gpio;
		target_state = &led1_state;
	} else {
		return;
	}

	*target_state = msg->led_value;
	ret = gpio_pin_set_dt(target_gpio, msg->led_value ? 1 : 0);
	if (ret != 0) {
		LOG_ERR("Failed to set LED%d: %d", msg->led_id, ret);
		return;
	}

	LOG_DBG("LED%d updated: %s (LED0=%s, LED1=%s)",
		msg->led_id, msg->led_value ? "ON" : "OFF",
		led0_state ? "ON" : "OFF", led1_state ? "ON" : "OFF");
}

ZBUS_LISTENER_DEFINE(leds_listener, leds_zbus_handler);

int led_init(void)
{
	int ret;

	if (!device_is_ready(led0_gpio.port)) {
		LOG_ERR("LED0 GPIO device not ready");
		return -ENODEV;
	}

	ret = gpio_pin_configure_dt(&led0_gpio, GPIO_OUTPUT_INACTIVE);
	if (ret != 0) {
		LOG_ERR("Failed to configure LED0 GPIO: %d", ret);
		return ret;
	}

	if (!device_is_ready(led1_gpio.port)) {
		LOG_ERR("LED1 GPIO device not ready");
		return -ENODEV;
	}

	ret = gpio_pin_configure_dt(&led1_gpio, GPIO_OUTPUT_INACTIVE);
	if (ret != 0) {
		LOG_ERR("Failed to configure LED1 GPIO: %d", ret);
		return ret;
	}

	ret = zbus_chan_add_obs(&leds_chan, &leds_listener, K_MSEC(200));
	if (ret != 0) {
		LOG_ERR("Failed to add LED listener: %d", ret);
		return ret;
	}

	ret = gpio_pin_set_dt(&led0_gpio, 0);
	ret |= gpio_pin_set_dt(&led1_gpio, 0);
	if (ret != 0) {
		LOG_ERR("Failed to initialize LEDs");
		return ret;
	}

	LOG_INF("LED driver initialized (LED0: GPIO %d, LED1: GPIO %d)",
		led0_gpio.pin, led1_gpio.pin);

	return 0;
}

