/**
 * @file cards.cpp
 * @brief RFID Card database implementation
 *
 * Uses ESP32 Preferences library for NVS storage.
 */

#include "cards.h"
#include <Preferences.h>

// NVS preferences instance
static Preferences prefs;
static int cardCount = 0;

void initCardDatabase() {
    prefs.begin(NVS_NAMESPACE, false);  // false = read/write mode
    cardCount = prefs.getInt(NVS_CARD_COUNT, 0);
    Serial.print("OK: Card database initialized, ");
    Serial.print(cardCount);
    Serial.println(" cards loaded");
}

int getCardCount() {
    return cardCount;
}

bool compareUID(byte* uid1, byte len1, byte* uid2, byte len2) {
    if (len1 != len2) return false;
    for (byte i = 0; i < len1; i++) {
        if (uid1[i] != uid2[i]) return false;
    }
    return true;
}

void formatUID(byte* uid, byte uidLength, char* buffer) {
    buffer[0] = '\0';
    for (byte i = 0; i < uidLength; i++) {
        char hex[4];
        sprintf(hex, "%02X", uid[i]);
        strcat(buffer, hex);
        if (i < uidLength - 1) strcat(buffer, ":");
    }
}

int findCardByUID(byte* uid, byte uidLength, QuestCard* card) {
    QuestCard temp;
    for (int i = 0; i < cardCount; i++) {
        if (getCard(i, &temp)) {
            if (compareUID(uid, uidLength, temp.uid, temp.uidLength)) {
                if (card != nullptr) {
                    memcpy(card, &temp, sizeof(QuestCard));
                }
                return i;
            }
        }
    }
    return -1;
}

bool getCard(int index, QuestCard* card) {
    if (index < 0 || index >= cardCount) return false;

    char key[16];
    sprintf(key, "card_%d", index);

    size_t len = prefs.getBytesLength(key);
    if (len != sizeof(QuestCard)) return false;

    prefs.getBytes(key, card, sizeof(QuestCard));
    return true;
}

bool addCard(QuestCard* card) {
    if (cardCount >= MAX_CARDS) {
        Serial.println("ERROR: Card database full");
        return false;
    }

    // Check if card already exists
    if (findCardByUID(card->uid, card->uidLength, nullptr) >= 0) {
        Serial.println("ERROR: Card already exists");
        return false;
    }

    char key[16];
    sprintf(key, "card_%d", cardCount);

    prefs.putBytes(key, card, sizeof(QuestCard));
    cardCount++;
    prefs.putInt(NVS_CARD_COUNT, cardCount);

    Serial.print("OK: Card added at index ");
    Serial.println(cardCount - 1);
    return true;
}

bool deleteCard(int index) {
    if (index < 0 || index >= cardCount) {
        Serial.println("ERROR: Invalid card index");
        return false;
    }

    // Shift all cards after this one down by one
    for (int i = index; i < cardCount - 1; i++) {
        QuestCard temp;
        char srcKey[16], dstKey[16];
        sprintf(srcKey, "card_%d", i + 1);
        sprintf(dstKey, "card_%d", i);

        prefs.getBytes(srcKey, &temp, sizeof(QuestCard));
        prefs.putBytes(dstKey, &temp, sizeof(QuestCard));
    }

    // Remove the last card entry
    char lastKey[16];
    sprintf(lastKey, "card_%d", cardCount - 1);
    prefs.remove(lastKey);

    cardCount--;
    prefs.putInt(NVS_CARD_COUNT, cardCount);

    Serial.print("OK: Card deleted, ");
    Serial.print(cardCount);
    Serial.println(" cards remaining");
    return true;
}

void clearAllCards() {
    for (int i = 0; i < cardCount; i++) {
        char key[16];
        sprintf(key, "card_%d", i);
        prefs.remove(key);
    }
    cardCount = 0;
    prefs.putInt(NVS_CARD_COUNT, 0);
    Serial.println("OK: All cards cleared");
}
