#include <Arduino.h>
#include <SPI.h>
#include <RadioLib.h>

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <OneWire.h>
#include <DallasTemperature.h>

// ================== LoRa pins (your working T3-S3 V1.2 setup) ==================
#define LORA_SCK   5
#define LORA_MISO  3
#define LORA_MOSI  6
#define LORA_CS    7
#define LORA_DIO1  33
#define LORA_RST   8
#define LORA_BUSY  34

SPIClass loraSPI(FSPI);
SPISettings loraSettings(2000000, MSBFIRST, SPI_MODE0);
SX1262 radio = new Module(LORA_CS, LORA_DIO1, LORA_RST, LORA_BUSY, loraSPI, loraSettings);

// ================== DS18B20 ==================
#define ONE_WIRE_PIN 41
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);

// ================== OLED (common LilyGO I2C OLED setup) ==================
#define OLED_SDA 18
#define OLED_SCL 17
#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// ================== App ==================
static const char* CMD_TEMP = "INCUBt0000";
static const char* ID_TEMP  = "INCUB";     // the ID field you asked for

float lastTempC = NAN;
unsigned long lastDisplayMs = 0;
const unsigned long DISPLAY_PERIOD_MS = 10000;

static void drawTempLarge(float tC) {
  display.clearDisplay();

  display.setTextColor(SSD1306_WHITE);

  // Big temperature
  display.setTextSize(3);  // "large font" on 128x64
  String line;
  if (isnan(tC)) {
    line = "--.-C";
  } else {
    line = String(tC, 1) + "C";
  }

  // Center it roughly
  int16_t x1, y1;
  uint16_t w, h;
  display.getTextBounds(line, 0, 0, &x1, &y1, &w, &h);
  int16_t x = (SCREEN_WIDTH - (int16_t)w) / 2;
  int16_t y = (SCREEN_HEIGHT - (int16_t)h) / 2;
  display.setCursor(x, y);
  display.print(line);

  // Small label at bottom
  display.setTextSize(1);
  display.setCursor(0, 56);
  display.print("Listening...");

  display.display();
}

static float readTempC() {
  sensors.requestTemperatures();              // blocking ~ up to 750ms at 12-bit
  float t = sensors.getTempCByIndex(0);
  if (t == DEVICE_DISCONNECTED_C) return NAN;
  return t;
}

void setup() {
  Serial.begin(115200);
  delay(200);
  Serial.println("Booted");

  // OLED init
  Wire.begin(OLED_SDA, OLED_SCL);
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println("OLED init failed (check I2C addr/pins).");
  } else {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("INCUB Temp Node");
    display.display();
  }

  // DS18B20 init
  sensors.begin();

  // LoRa init
  loraSPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);

  int state = radio.begin();
  if (state != RADIOLIB_ERR_NONE) {
    Serial.print("radio.begin() failed, code=");
    Serial.println(state);
    while (true) delay(1000);
  }

  // Match your network / receiver settings
  radio.setFrequency(868.0);
  radio.setBandwidth(125.0);
  radio.setSpreadingFactor(9);
  radio.setCodingRate(5);        // 4/5
  radio.setPreambleLength(8);
  radio.setSyncWord(0x34);
  radio.setOutputPower(17);
  radio.setCRC(true);            // keep consistent with your other nodes

  Serial.println("Radio configured. Listening...");

  // First reading + display
  lastTempC = readTempC();
  drawTempLarge(lastTempC);
  lastDisplayMs = millis();
}

void loop() {
  // Update temperature + OLED every 10 seconds
  unsigned long now = millis();
  if (now - lastDisplayMs >= DISPLAY_PERIOD_MS) {
    lastTempC = readTempC();
    Serial.print("TempC: ");
    Serial.println(lastTempC, 2);
    if (display.width() > 0) drawTempLarge(lastTempC);
    lastDisplayMs = now;
  }

  // Listen for command
  String rx;
  int state = radio.receive(rx);

  if (state == RADIOLIB_ERR_NONE) {
    rx.trim();
    Serial.print("RX: '");
    Serial.print(rx);
    Serial.println("'");

    if (rx == CMD_TEMP) {
      // Build: ID,temperature,nan,nan,nan
      // Use the most recent reading (or take a fresh one if you prefer)
      float t = lastTempC;
      if (isnan(t)) t = readTempC();

      String out = String(ID_TEMP) + "," + String(t, 2) + ",nan,nan,nan";
      Serial.print("TX: ");
      Serial.println(out);

      int txState = radio.transmit(out);
      if (txState == RADIOLIB_ERR_NONE) {
        Serial.println("TX OK");
      } else {
        Serial.print("TX failed, code=");
        Serial.println(txState);
      }
    }
  } else if (state != RADIOLIB_ERR_RX_TIMEOUT) {
    Serial.print("RX error, code=");
    Serial.println(state);
  }

  delay(10);
}