#include <WiFi.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ThingSpeak.h>

#define DHTPIN 4
#define DHTTYPE DHT22
#define POTENTIOMETER_GLUCOSE_PIN 33
#define POTENTIOMETER_HEART_PIN 34
#define SWITCH_PIN 27

DHT dht(DHTPIN, DHTTYPE);

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

struct Patient {
  const char* id;
  const char* name;
  float glucoseLevel;
  float temperatureC;
  int heartRate;
  unsigned long channelID;
  const char* apiKey;
};

Patient patients[] = {
  {"AIB024589101", "Razaq", 0, 0, 0, 2577535, "7VA1PX66REA0DB06"},
  {"E28068940194", "Rifat", 0, 0, 0, 2577534, "DCD5RWGJYBLNA2S0"},
  {"DA1504821093", "Angga", 0, 0, 0, 2577536, "M5HQVCVAQWGGIF99"},
  {"AD5020495123", "Bilal", 0, 0, 0, 2577537, "YANBXOELEY7BTFQE"},
};

Patient* currentPatient = &patients[0];
bool monitoringActive = false;

char ssid[] = "Wokwi-GUEST";
char pass[] = "";

WiFiClient client;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, pass);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

  ThingSpeak.begin(client); // Initialize ThingSpeak

  dht.begin();
  pinMode(POTENTIOMETER_GLUCOSE_PIN, INPUT);
  pinMode(POTENTIOMETER_HEART_PIN, INPUT);
  pinMode(SWITCH_PIN, INPUT_PULLUP);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("Patient Monitor");
  display.display();
  delay(2000);

  Serial.println("Enter patient ID to switch (e.g., AIB024589101):");
}

void loop() {
  checkSwitch();
  if (monitoringActive) {
    readSensors();
    sendSensorData();
    displayData();
    printToSerial();
  } else {
    displayStandby();
  }
  checkRFID();
}

void readSensors() {
  currentPatient->glucoseLevel = analogRead(POTENTIOMETER_GLUCOSE_PIN) * (240.0 / 4095.0);
  currentPatient->temperatureC = dht.readTemperature();

  if (isnan(currentPatient->temperatureC)) {
    Serial.println("Error: Could not read temperature data");
    currentPatient->temperatureC = 0;
  } else {
    Serial.print("Temperature: ");
    Serial.print(currentPatient->temperatureC);
    Serial.println(" °C");
  }

  // Correct scaling factor for heart rate
  currentPatient->heartRate = analogRead(POTENTIOMETER_HEART_PIN) * (150.0 / 4095.0);
  if (currentPatient->heartRate > 150) {
    currentPatient->heartRate = 150;
  }
}

void sendSensorData() {
  ThingSpeak.setField(1, currentPatient->temperatureC);
  ThingSpeak.setField(2, currentPatient->glucoseLevel);
  ThingSpeak.setField(3, currentPatient->heartRate);

  int response = ThingSpeak.writeFields(currentPatient->channelID, currentPatient->apiKey);
  if (response == 200) {
    Serial.println("Data sent to ThingSpeak successfully");
  } else {
    Serial.println("Error sending data to ThingSpeak: " + String(response));
  }
}

void displayData() {
  display.clearDisplay();

  display.setTextSize(1);

  const char* title1 = "HEALTH TECH";
  int16_t x1, y1;
  uint16_t w1, h1;
  display.getTextBounds(title1, 0, 0, &x1, &y1, &w1, &h1);
  display.setCursor((SCREEN_WIDTH - w1) / 2, 0);
  display.print(title1);

  const char* title2 = "PATIENT MONITOR";
  int16_t x2, y2;
  uint16_t w2, h2;
  display.getTextBounds(title2, 0, 0, &x2, &y2, &w2, &h2);
  display.setCursor((SCREEN_WIDTH - w2) / 2, 8);
  display.print(title2);

  display.setCursor(0, 24);
  display.setTextSize(1);
  display.print("Patient: ");
  display.println(currentPatient->name);

  display.print("Glucose:");
  display.print(currentPatient->glucoseLevel, 2);
  display.println(" mg/dL");

  display.print("Temp:");
  display.print(currentPatient->temperatureC, 2);
  display.println(" C");

  display.print("Heart Rate:");
  display.print(currentPatient->heartRate, 2);
  display.println(" BPM");

  display.display();
}

void displayStandby() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(1);
  display.println("Standby");
  display.display();
}

void printToSerial() {
  Serial.print("Patient: ");
  Serial.println(currentPatient->name);

  Serial.print("Glucose Level: ");
  Serial.print(currentPatient->glucoseLevel, 2);
  Serial.println(" mg/dL");

  Serial.print("Body Temperature: ");
  Serial.print(currentPatient->temperatureC, 2);
  Serial.println(" °C");

  Serial.print("Heart Rate: ");
  Serial.print(currentPatient->heartRate, 2);
  Serial.println(" BPM");
  delay(2000);
}

void checkSwitch() {
  bool switchState = digitalRead(SWITCH_PIN) == LOW;
  if (monitoringActive != switchState) {
    monitoringActive = switchState;

    if (monitoringActive) {
      Serial.println("Enter patient ID to switch (e.g., AIB024589101):");
    }
  }
}

void checkRFID() {
  if (Serial.available() > 0) {
    String id = Serial.readStringUntil('\n');
    id.trim();

    bool patientFound = false;
    for (int i = 0; i < sizeof(patients) / sizeof(patients[0]); i++) {
      if (id == patients[i].id) {
        currentPatient = &patients[i];
        patientFound = true;
        Serial.print("Switched to patient: ");
        Serial.println(currentPatient->name);
        break;
      }
    }
    if (!patientFound) {
      Serial.println("Invalid patient ID.");
    }
  }
}