#include "esp_camera.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <base64.h>
#include <Adafruit_Fingerprint.h>

// WiFi
const char *ssid = "GalaxyA13";
const char *password = "1234567890";

// Google Script
String scriptURL = "https://script.google.com/macros/s/AKfycbys3c8TGmrfgYwTnfORsVePGKFwkSFDCXiJaItRAL384N2Ss0fL6Brf9ouGH4fpAveU/exec";

// Twilio
String accountSID = "ACc28bc5ee1636531b0b62178aacf49349";
String authToken = "923708c252e0a3527273132ae2de6e44";
String fromWhatsApp = "whatsapp:+14155238886";
String toWhatsApp = "whatsapp:+918746826539";

// Fingerprint UART
HardwareSerial mySerial(1);
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

// Name mapping
String getName(int id)
{
    if (id == 1)
        return "MADAN.R";
    if (id == 2)
        return "Chandu";
    if (id == 3)
        return "MAX";
    if (id == 4)
        return "Madannayak";
    return "Unknown";
}

void setup()
{
    Serial.begin(115200);

    // Fingerprint serial
    mySerial.begin(57600, SERIAL_8N1, 14, 15);

    finger.begin(57600);

    if (!finger.verifyPassword())
    {
        Serial.println("Fingerprint not detected");
        while (1)
            ;
    }

    // WiFi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
        delay(500);

    // Camera config
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = 5;
    config.pin_d1 = 18;
    config.pin_d2 = 19;
    config.pin_d3 = 21;
    config.pin_d4 = 36;
    config.pin_d5 = 39;
    config.pin_d6 = 34;
    config.pin_d7 = 35;
    config.pin_xclk = 0;
    config.pin_pclk = 22;
    config.pin_vsync = 25;
    config.pin_href = 23;
    config.pin_sscb_sda = 26;
    config.pin_sscb_scl = 27;
    config.pin_pwdn = 32;
    config.pin_reset = -1;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;

    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;

    esp_camera_init(&config);
}

void loop()
{

    int id = getFingerprintID();

    if (id > 0)
    {
        String name = getName(id);
        Serial.println("Detected: " + name);

        captureAndSend(name);
        delay(5000);
    }
}

// Fingerprint detect
int getFingerprintID()
{
    if (finger.getImage() != FINGERPRINT_OK)
        return -1;
    if (finger.image2Tz() != FINGERPRINT_OK)
        return -1;
    if (finger.fingerSearch() != FINGERPRINT_OK)
        return -1;

    return finger.fingerID;
}

// Capture + upload + WhatsApp
void captureAndSend(String name)
{

    camera_fb_t *fb = esp_camera_fb_get();

    String imageBase64 = base64::encode(fb->buf, fb->len);
    String filename = name + ".jpg";

    HTTPClient http;
    http.begin(scriptURL);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    String data = "image=" + imageBase64 + "&filename=" + filename;

    http.POST(data);

    String imageUrl = http.getString();
    http.end();

    esp_camera_fb_return(fb);

    sendWhatsApp(name, imageUrl);
}

// Twilio WhatsApp
void sendWhatsApp(String name, String imageUrl)
{

    HTTPClient http;

    String url = "https://api.twilio.com/2010-04-01/Accounts/" + accountSID + "/Messages.json";

    http.begin(url);
    http.setAuthorization(accountSID.c_str(), authToken.c_str());

    http.addHeader("Content-Type", "application/x-www-form-urlencoded");

    String msg = "From=" + fromWhatsApp +
                 "&To=" + toWhatsApp +
                 "&Body=" + name + " detected" +
                 "&MediaUrl=" + imageUrl;

    http.POST(msg);
    http.end();
}