#include <iostream>
#include <string>
#include <ctime>
using namespace std;

string hashPassword(string password, string salt) {

    string result = password + salt;
    for (int round = 0; round < 1000; round++) {
        string temp = "";
        for (int i = 0; i < (int)result.length(); i++) {

            char c = (char)((result[i] ^ (round % 256) ^ (i % 256)) & 0xFF);

            if (c < 32 || c > 126) c = (char)(((unsigned char)c % 95) + 32);
            temp += c;
        }
        for (int i = 0; i < (int)result.length(); i++) {
            temp[i % temp.length()] ^= result[i];
            if (temp[i % temp.length()] < 32 || temp[i % temp.length()] > 126)
                temp[i % temp.length()] = (char)(((unsigned char)temp[i % temp.length()] % 95) + 32);
        }
        result = temp;
    }
    if ((int)result.length() > 32) result = result.substr(0, 32);
    return result;
}

string hashPass(string password, string username) {
    return hashPassword(password, username + "DebtEase_Salt_2026");
}

struct Item {
    string name;
    int    quantity;
    double price;
};

struct BorrowSession {
    string  date;
    string  dueDate;
    Item*   items;
    int     itemCount;
    int     itemCap;
    double  total;
    double  paid;
};

struct Borrower {
    string         userID;
    string         username;
    string         passHash;
    string         fullName;
    string         contact;
    int            lenderIndex;
    BorrowSession* sessions;
    int            sessionCount;
    int            sessionCap;
};

struct Lender {
    string username;
    string passHash;            
    string fullName;
    string storeName;
    string contact;
};

Lender*   lenders      = new Lender[2];
int       lenderCount  = 0;
int       lenderCap    = 2;

Borrower* borrowers     = new Borrower[2];
int       borrowerCount = 0;
int       borrowerCap   = 2;

void growLenders() {
    lenderCap *= 2;
    Lender* tmp = new Lender[lenderCap];
    for (int i = 0; i < lenderCount; i++) tmp[i] = lenders[i];
    delete[] lenders;
    lenders = tmp;
}

void growBorrowers() {
    borrowerCap *= 2;
    Borrower* tmp = new Borrower[borrowerCap];
    for (int i = 0; i < borrowerCount; i++) tmp[i] = borrowers[i];
    delete[] borrowers;
    borrowers = tmp;
}

void initSession(BorrowSession& s) {
    s.itemCap   = 4;
    s.itemCount = 0;
    s.total     = 0;
    s.paid      = 0;
    s.items     = new Item[s.itemCap];
}

void addItemToSession(BorrowSession& s, Item item) {
    if (s.itemCount == s.itemCap) {
        s.itemCap *= 2;
        Item* tmp = new Item[s.itemCap];
        for (int i = 0; i < s.itemCount; i++) tmp[i] = s.items[i];
        delete[] s.items;
        s.items = tmp;
    }
    s.items[s.itemCount++] = item;
    s.total += item.quantity * item.price;
}

void addSessionToBorrower(Borrower& b, BorrowSession s) {
    if (b.sessionCount == b.sessionCap) {
        b.sessionCap *= 2;
        BorrowSession* tmp = new BorrowSession[b.sessionCap];
        for (int i = 0; i < b.sessionCount; i++) tmp[i] = b.sessions[i];
        delete[] b.sessions;
        b.sessions = tmp;
    }
    b.sessions[b.sessionCount++] = s;
}

void initBorrower(Borrower& b) {
    b.sessionCap   = 4;
    b.sessionCount = 0;
    b.sessions     = new BorrowSession[b.sessionCap];
}

void pressEnter() {
    cout << "\n  Press Enter to continue...";
    cin.ignore();
    cin.get();
}

string getDate() {
    time_t now = time(0);
    tm* t = localtime(&now);
    string d = to_string(t->tm_mday);
    string m = to_string(1 + t->tm_mon);
    string y = to_string(1900 + t->tm_year);
    if (d.length() == 1) d = "0" + d;
    if (m.length() == 1) m = "0" + m;
    return y + "-" + m + "-" + d;
}

string pad(string s, int w) {
    while ((int)s.length() < w) s += " ";
    if ((int)s.length() > w)   s = s.substr(0, w);
    return s;
}

string dbl(double v) {
    if (v < 0) v = 0;
    long whole = (long)v;
    int  cents = (int)((v - whole) * 100.0 + 0.5);
    if (cents >= 100) { whole++; cents = 0; }
    string c = to_string(cents);
    if (c.length() == 1) c = "0" + c;
    return to_string(whole) + "." + c;
}

string formatID(int n) {
    string s = to_string(n);
    while ((int)s.length() < 5) s = "0" + s;
    return s;
}

double getBorrowerBalance(int bIdx) {
    double total = 0, paid = 0;
    for (int s = 0; s < borrowers[bIdx].sessionCount; s++) {
        total += borrowers[bIdx].sessions[s].total;
        paid  += borrowers[bIdx].sessions[s].paid;
    }
    return total - paid;
}

string getNearestDue(int bIdx) {
    string nearest = "";
    for (int s = 0; s < borrowers[bIdx].sessionCount; s++) {
        string d = borrowers[bIdx].sessions[s].dueDate;
        if (nearest == "" || d < nearest) nearest = d;
    }
    return nearest == "" ? "N/A" : nearest;
}

bool usernameExists(string uname) {
    for (int i = 0; i < lenderCount; i++)
        if (lenders[i].username == uname) return true;
    for (int i = 0; i < borrowerCount; i++)
        if (borrowers[i].username == uname) return true;
    return false;
}

bool userIDExists(string uid) {
    for (int i = 0; i < borrowerCount; i++)
        if (borrowers[i].userID == uid) return true;
    return false;
}

string inputStr(string prompt) {
    string val = "";
    while (val == "") {
        cout << prompt;
        getline(cin, val);
        if (val == "") cout << "  [!] Cannot be empty. Try again.\n";
    }
    return val;
}

int inputInt(string prompt) {
    string line = "";
    while (true) {
        cout << prompt;
        getline(cin, line);
        if (line == "") { cout << "  INVALID INPUT!!! Try again.\n"; continue; }
        bool isNum = true;
        bool hasSign = (line[0] == '-');
        int start = hasSign ? 1 : 0;
        if (start >= (int)line.length()) isNum = false;
        for (int i = start; i < (int)line.length() && isNum; i++)
            if (line[i] < '0' || line[i] > '9') isNum = false;
        if (!isNum) { cout << "  INVALID INPUT!!! Try again.\n"; continue; }
        return stoi(line);
    }
}

double inputDbl(string prompt) {
    string line = "";
    while (true) {
        cout << prompt;
        getline(cin, line);
        if (line == "") { cout << "  INVALID INPUT!!! Try again.\n"; continue; }
        bool ok = true; bool dotSeen = false;
        for (int i = 0; i < (int)line.length() && ok; i++) {
            if (line[i] == '.' && !dotSeen) { dotSeen = true; continue; }
            if (line[i] < '0' || line[i] > '9') ok = false;
        }
        if (!ok) { cout << "  INVALID INPUT!!! Try again.\n"; continue; }
        return stod(line);
    }
}

void printLine(int w) {
    cout << "  +";
    for (int i = 0; i < w; i++) cout << "-";
    cout << "+\n";
}

void printHeader(string title, int w) {
    printLine(w);
    int space = (w - (int)title.length()) / 2;
    if (space < 0) space = 0;
    cout << "  |";
    for (int i = 0; i < space; i++) cout << " ";
    cout << title;
    int rest = w - space - (int)title.length();
    for (int i = 0; i < rest; i++) cout << " ";
    cout << "|\n";
    printLine(w);
}

void printRow(string left, int w) {
    cout << "  | " << pad(left, w - 2) << " |\n";
}

void displayBorrowerDetails(int bIdx) {
    Borrower& b = borrowers[bIdx];

    cout << "\n";
    printHeader("BORROWER DETAILS", 64);
    printRow("User ID  : " + b.userID, 64);
    printRow("Name     : " + b.fullName, 64);
    printRow("Username : " + b.username, 64);
    printRow("Contact  : " + b.contact, 64);
    printLine(64);

    if (b.sessionCount == 0) {
        printRow("No borrow sessions yet.", 64);
        printLine(64);
        return;
    }

    double grandTotal = 0, grandPaid = 0;

    for (int s = 0; s < b.sessionCount; s++) {
        BorrowSession& ses = b.sessions[s];
        cout << "\n";
        printHeader("BORROW SESSION #" + to_string(s + 1), 64);
        printRow("Date Borrowed : " + ses.date, 64);
        printRow("Due Date      : " + ses.dueDate, 64);
        printLine(64);

        cout << "  | " << pad("  ITEM NAME", 24)
             << pad("QTY", 6)
             << pad("PRICE", 14)
             << pad("SUBTOTAL", 16) << " |\n";
        printLine(64);

        for (int i = 0; i < ses.itemCount; i++) {
            double sub = ses.items[i].quantity * ses.items[i].price;
            cout << "  | " << pad("  " + ses.items[i].name, 24)
                 << pad(to_string(ses.items[i].quantity), 6)
                 << pad("P" + dbl(ses.items[i].price), 14)
                 << pad("P" + dbl(sub), 16) << " |\n";
        }
        printLine(64);

        double bal = ses.total - ses.paid;
        printRow("Session Total  : P" + dbl(ses.total), 64);
        printRow("Amount Paid    : P" + dbl(ses.paid), 64);
        printRow("Remaining Bal  : P" + dbl(bal), 64);
        printLine(64);

        grandTotal += ses.total;
        grandPaid  += ses.paid;
    }

    cout << "\n";
    printHeader("GRAND SUMMARY", 64);
    printRow("Total Borrowed : P" + dbl(grandTotal), 64);
    printRow("Total Paid     : P" + dbl(grandPaid),  64);
    printRow("BALANCE OWED   : P" + dbl(grandTotal - grandPaid), 64);
    printLine(64);
}

void recalcSession(BorrowSession& ses) {
    ses.total = 0;
    for (int i = 0; i < ses.itemCount; i++)
        ses.total += ses.items[i].quantity * ses.items[i].price;
}

void deleteItemFromSession(BorrowSession& ses) {
    if (ses.itemCount == 0) {
        cout << "  No items to delete.\n";
        pressEnter();
        return;
    }

    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("DELETE ITEM", 64);
        cout << "  | " << pad("#", 4) << pad("ITEM NAME", 24)
             << pad("QTY", 6) << pad("PRICE", 14) << pad("SUBTOTAL", 12) << " |\n";
        printLine(64);

        for (int i = 0; i < ses.itemCount; i++) {
            double sub = ses.items[i].quantity * ses.items[i].price;
            cout << "  | " << pad("[" + to_string(i + 1) + "]", 4)
                 << pad(ses.items[i].name, 24)
                 << pad(to_string(ses.items[i].quantity), 6)
                 << pad("P" + dbl(ses.items[i].price), 14)
                 << pad("P" + dbl(sub), 12) << " |\n";
        }
        printLine(64);
        cout << "  [0] Back\n";

        int choice = inputInt("  Select item number to DELETE: ");
        if (choice == 0) { back = true; break; }
        if (choice < 1 || choice > ses.itemCount) {
            cout << "  INVALID INPUT!!!\n"; continue;
        }

        string delName = ses.items[choice - 1].name;

        for (int i = choice - 1; i < ses.itemCount - 1; i++)
            ses.items[i] = ses.items[i + 1];
        ses.itemCount--;
        recalcSession(ses);
        cout << "  Item '" << delName << "' deleted.\n";
        cout << "  New Session Total: P" << dbl(ses.total) << "\n";
        back = true;
    }
}

void addBorrowSession(int bIdx) {
    BorrowSession ses;
    initSession(ses);
    ses.date = getDate();

    cout << "\n";
    printHeader("ADD BORROW SESSION", 52);
    printRow("Print [0] to cancel", 52);
    printLine(52);
    cout << "  Date Borrowed : " << ses.date << "\n";

    while (true) {
        cout << "  Due Date (YYYY-MM-DD): ";
        string dd; getline(cin, dd);
        if (dd == "0") {
            cout << "  Cancelled.\n"; pressEnter(); return;
        }
        if (dd.length() != 10 || dd[4] != '-' || dd[7] != '-') {
            cout << "  INVALID INPUT!!! Format must be YYYY-MM-DD\n"; continue;
        }
        ses.dueDate = dd;
        break;
    }
    
    bool doneAdding = false;
    while (!doneAdding) {
        cout << "\n";
        printHeader("ITEM LIST", 64);
        if (ses.itemCount == 0) {
            printRow("  (no items yet)", 64);
        } else {
            cout << "  | " << pad("#", 4) << pad("ITEM NAME", 22)
                 << pad("QTY", 6) << pad("PRICE", 14) << pad("SUBTOTAL", 14) << " |\n";
            printLine(64);
            for (int i = 0; i < ses.itemCount; i++) {
                double sub = ses.items[i].quantity * ses.items[i].price;
                cout << "  | " << pad(to_string(i + 1), 4)
                     << pad(ses.items[i].name, 22)
                     << pad(to_string(ses.items[i].quantity), 6)
                     << pad("P" + dbl(ses.items[i].price), 14)
                     << pad("P" + dbl(sub), 14) << " |\n";
            }
        }
        printLine(64);
        cout << "  Current Total: P" << dbl(ses.total) << "\n";
        cout << "\n";
        printHeader("ITEM OPTIONS", 40);
        printRow("[1] Add Item", 40);
        printRow("[2] Remove Item", 40);
        printRow("[3] Save Session", 40);
        printRow("[0] Cancel session", 40);
        printLine(40);

        int opt = inputInt("  Choice: ");
        if (opt == 0) { cout << "  Session discarded.\n"; pressEnter(); return; }
        else if (opt == 1) {
            Item item;
            item.name = inputStr("  Item Name    : ");
            item.quantity = inputInt("  Quantity      : ");
            if (item.quantity <= 0) { cout << "  INVALID INPUT!!!\n"; continue; }
            item.price = inputDbl("  Price (P)     : ");
            if (item.price <= 0) { cout << "  INVALID INPUT!!!\n"; continue; }
            double sub = item.quantity * item.price;
            cout << "  Subtotal: P" << dbl(sub) << "\n";
            addItemToSession(ses, item);
        }
        else if (opt == 2) deleteItemFromSession(ses);
        else if (opt == 3) {
            if (ses.itemCount == 0) {
                cout << "  Cannot save empty session. Add at least 1 item.\n"; continue;
            }
            doneAdding = true;
        }
        else cout << "  INVALID INPUT!!!\n";
    }

    addSessionToBorrower(borrowers[bIdx], ses);

    cout << "\n";
    printHeader("SESSION SAVED", 52);
    printRow("Date    : " + ses.date, 52);
    printRow("Due     : " + ses.dueDate, 52);
    printRow("Total   : P" + dbl(ses.total), 52);
    printLine(52);
    pressEnter();
}

void addThingsToExisting(int bIdx) {
    Borrower& b = borrowers[bIdx];
    if (b.sessionCount == 0) {
        cout << "  No sessions found. Use 'Add New Borrow' instead.\n";
        pressEnter(); return;
    }

    cout << "\n";
    printHeader("SELECT SESSION TO ADD ITEMS", 52);
    for (int s = 0; s < b.sessionCount; s++) {
        cout << "  | " << pad("[" + to_string(s + 1) + "] Due: "
             + b.sessions[s].dueDate
             + "  Total: P" + dbl(b.sessions[s].total), 50) << " |\n";
    }
    printLine(52);
    cout << "  [0] Back\n";

    int choice = inputInt("  Select session: ");
    if (choice == 0) return;
    if (choice < 1 || choice > b.sessionCount) {
        cout << "  INVALID INPUT!!!\n"; pressEnter(); return;
    }

    BorrowSession& ses = b.sessions[choice - 1];
    bool done = false;
    while (!done) {
        cout << "\n";
        printHeader("ADD / DELETE ITEMS", 40);
        printRow("[1] Add Item", 40);
        printRow("[2] Delete Item", 40);
        printRow("[0] Back", 40);
        printLine(40);

        int opt = inputInt("  Choice: ");
        if (opt == 0) done = true;
        else if (opt == 1) {
            Item item;
            item.name = inputStr("  Item Name  : ");
            item.quantity = inputInt("  Quantity   : ");
            if (item.quantity <= 0) { cout << "  INVALID INPUT!!!\n"; continue; }
            item.price = inputDbl("  Price (P)  : ");
            if (item.price <= 0) { cout << "  INVALID INPUT!!!\n"; continue; }
            addItemToSession(ses, item);
            cout << "  Item added! New Total: P" << dbl(ses.total) << "\n";
        }
        else if (opt == 2) deleteItemFromSession(ses);
        else cout << "  INVALID INPUT!!!\n";
    }
}

void payBorrowed(int bIdx) {
    Borrower& b = borrowers[bIdx];
    if (b.sessionCount == 0) {
        cout << "  No sessions found.\n"; pressEnter(); return;
    }

    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("PAY BORROWED THINGS", 68);
        cout << "  | " << pad("#", 4) << pad("Due Date", 14)
             << pad("Total", 14) << pad("Paid", 14) << pad("Balance", 18) << " |\n";
        printLine(68);

        int active = 0;
        for (int s = 0; s < b.sessionCount; s++) {
            double bal = b.sessions[s].total - b.sessions[s].paid;
            if (bal > 0.001) {
                active++;
                cout << "  | " << pad("[" + to_string(s + 1) + "]", 4)
                     << pad(b.sessions[s].dueDate, 14)
                     << pad("P" + dbl(b.sessions[s].total), 14)
                     << pad("P" + dbl(b.sessions[s].paid), 14)
                     << pad("P" + dbl(bal), 18) << " |\n";
            }
        }
        printLine(68);

        if (active == 0) {
            cout << "  All sessions are FULLY PAID!\n";
            pressEnter(); return;
        }

        cout << "  [0] Back\n";
        int choice = inputInt("  Select session to pay: ");
        if (choice == 0) { back = true; break; }
        if (choice < 1 || choice > b.sessionCount) {
            cout << "  INVALID INPUT!!!\n"; continue;
        }

        BorrowSession& ses = b.sessions[choice - 1];
        double balance = ses.total - ses.paid;
        if (balance <= 0.001) {
            cout << "  This session is already FULLY PAID.\n"; pressEnter(); continue;
        }

        cout << "  Remaining Balance: P" << dbl(balance) << "\n";
        double payment = inputDbl("  Enter payment amount: P");

        if (payment <= 0) { cout << "  INVALID INPUT!!!\n"; continue; }
        if (payment > balance) {
            cout << "  Amount exceeds balance. Adjusted to P" << dbl(balance) << "\n";
            payment = balance;
        }

        ses.paid += payment;
        double newBal = ses.total - ses.paid;

        cout << "\n";
        printHeader("PAYMENT RECEIPT", 54);
        printRow("Payment Made   : P" + dbl(payment), 54);
        printRow("Total Paid     : P" + dbl(ses.paid), 54);
        printRow("Remaining Bal  : P" + dbl(newBal), 54);
        printLine(54);

        if (newBal <= 0.001) cout << "  FULLY PAID! Great!\n";
        else                  cout << "  Partial payment recorded.\n";
        pressEnter();
        back = true;
    }
}

void mergeSortDue(int* arr, int left, int right) {
    if (left >= right) return;
    int mid = (left + right) / 2;
    mergeSortDue(arr, left, mid);
    mergeSortDue(arr, mid + 1, right);

    int n1 = mid - left + 1, n2 = right - mid;
    int* L = new int[n1];
    int* R = new int[n2];
    for (int i = 0; i < n1; i++) L[i] = arr[left + i];
    for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (getNearestDue(L[i]) <= getNearestDue(R[j])) arr[k++] = L[i++];
        else                                              arr[k++] = R[j++];
    }
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
    delete[] L; delete[] R;
}

void mergeSortBalance(int* arr, int left, int right) {
    if (left >= right) return;
    int mid = (left + right) / 2;
    mergeSortBalance(arr, left, mid);
    mergeSortBalance(arr, mid + 1, right);

    int n1 = mid - left + 1, n2 = right - mid;
    int* L = new int[n1];
    int* R = new int[n2];
    for (int i = 0; i < n1; i++) L[i] = arr[left + i];
    for (int j = 0; j < n2; j++) R[j] = arr[mid + 1 + j];

    int i = 0, j = 0, k = left;
    while (i < n1 && j < n2) {
        if (getBorrowerBalance(L[i]) >= getBorrowerBalance(R[j])) arr[k++] = L[i++];
        else                                                        arr[k++] = R[j++];
    }
    while (i < n1) arr[k++] = L[i++];
    while (j < n2) arr[k++] = R[j++];
    delete[] L; delete[] R;
}

void sortByUsername(int* arr, int size) {
    for (int i = 1; i < size; i++) {
        int key = arr[i], j = i - 1;
        while (j >= 0 && borrowers[arr[j]].username > borrowers[key].username) {
            arr[j + 1] = arr[j]; j--;
        }
        arr[j + 1] = key;
    }
}

int binarySearch(int* arr, int size, string target) {
    int lo = 0, hi = size - 1;
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (borrowers[arr[mid]].username == target) return arr[mid];
        else if (borrowers[arr[mid]].username < target) lo = mid + 1;
        else hi = mid - 1;
    }
    return -1;
}

int* getLenderBorrowers(int lenderIdx, int& count) {
    count = 0;
    for (int i = 0; i < borrowerCount; i++)
        if (borrowers[i].lenderIndex == lenderIdx) count++;
    if (count == 0) return nullptr;
    int* arr = new int[count];
    int k = 0;
    for (int i = 0; i < borrowerCount; i++)
        if (borrowers[i].lenderIndex == lenderIdx) arr[k++] = i;
    return arr;
}

void borrowerActionMenu(int bIdx) {
    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader(borrowers[bIdx].fullName + "  -  ACTIONS", 46);
        printRow("[1] Add Things (New Borrow Session)", 46);
        printRow("[2] Add Items to Existing Session",   46);
        printRow("[3] Pay Borrowed Things",             46);
        printRow("[4] View Full Details",               46);
        printRow("[0] Back",                            46);
        printLine(46);

        int c = inputInt("  Choice: ");
        if (c == 0) back = true;
        else if (c == 1) addBorrowSession(bIdx);
        else if (c == 2) addThingsToExisting(bIdx);
        else if (c == 3) payBorrowed(bIdx);
        else if (c == 4) { displayBorrowerDetails(bIdx); pressEnter(); }
        else cout << "  INVALID INPUT!!!\n";
    }
}

void seeDueDates(int lenderIdx) {
    int count = 0;
    int* arr = getLenderBorrowers(lenderIdx, count);
    if (!arr || count == 0) {
        cout << "  No borrowers found.\n"; pressEnter();
        if (arr) delete[] arr; return;
    }

    mergeSortDue(arr, 0, count - 1);

    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("DUE DATES  (Earliest First - Merge Sorted)", 66);
        cout << "  | " << pad("#", 4) << pad("NAME", 22)
             << pad("NEAREST DUE", 16) << pad("BALANCE", 20) << " |\n";
        printLine(66);

        int shown = 0;
        for (int i = 0; i < count; i++) {
            if (borrowers[arr[i]].sessionCount == 0) continue;
            shown++;
            cout << "  | " << pad("[" + to_string(i + 1) + "]", 4)
                 << pad(borrowers[arr[i]].fullName, 22)
                 << pad(getNearestDue(arr[i]), 16)
                 << pad("P" + dbl(getBorrowerBalance(arr[i])), 20) << " |\n";
        }
        if (shown == 0) { printRow("  No active borrowers.", 66); }
        printLine(66);
        cout << "  [0] Back\n";

        int choice = inputInt("  Select borrower: ");
        if (choice == 0) { back = true; break; }
        if (choice < 1 || choice > count) { cout << "  INVALID INPUT!!!\n"; continue; }
        displayBorrowerDetails(arr[choice - 1]);
        pressEnter();
        back = true;
    }
    delete[] arr;
}

void seeAllBorrowers(int lenderIdx) {
    int count = 0;
    int* arr = getLenderBorrowers(lenderIdx, count);
    if (!arr || count == 0) {
        cout << "  No borrowers registered.\n"; pressEnter();
        if (arr) delete[] arr; return;
    }

    mergeSortBalance(arr, 0, count - 1);

    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("ALL BORROWERS  (Biggest Balance First - Merge Sorted)", 66);
        cout << "  | " << pad("#", 4) << pad("ID", 8) << pad("NAME", 24)
             << pad("BALANCE", 26) << " |\n";
        printLine(66);
        for (int i = 0; i < count; i++) {
            cout << "  | " << pad("[" + to_string(i + 1) + "]", 4)
                 << pad(borrowers[arr[i]].userID, 8)
                 << pad(borrowers[arr[i]].fullName, 24)
                 << pad("P" + dbl(getBorrowerBalance(arr[i])), 26) << " |\n";
        }
        printLine(66);
        cout << "  [0] Back\n";

        int choice = inputInt("  Select borrower: ");
        if (choice == 0) { back = true; break; }
        if (choice < 1 || choice > count) { cout << "  INVALID INPUT!!!\n"; continue; }
        borrowerActionMenu(arr[choice - 1]);
        back = true;
    }
    delete[] arr;
}

void searchBorrower(int lenderIdx) {
    int count = 0;
    int* arr = getLenderBorrowers(lenderIdx, count);
    if (!arr || count == 0) {
        cout << "  No borrowers found.\n"; pressEnter();
        if (arr) delete[] arr; return;
    }

    cout << "\n";
    printHeader("SEARCH BORROWER", 54);
    printRow("Search by User ID  (e.g. 00001)", 54);
    printRow("  or by Full Name  (e.g. Juan Dela Cruz)", 54);
    printLine(54);

    string target = inputStr("  Enter User ID or Full Name: ");

    for (int i = 1; i < count; i++) {
        int key = arr[i], j = i - 1;
        while (j >= 0 && borrowers[arr[j]].userID > borrowers[key].userID) {
            arr[j + 1] = arr[j]; j--;
        }
        arr[j + 1] = key;
    }

    int result = -1;

    int lo = 0, hi = count - 1;
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (borrowers[arr[mid]].userID == target) {
            result = arr[mid]; break;
        } else if (borrowers[arr[mid]].userID < target) lo = mid + 1;
        else hi = mid - 1;
    }

    if (result == -1) {
        for (int i = 0; i < count; i++) {
            if (borrowers[arr[i]].fullName == target) {
                result = arr[i]; break;
            }
        }
    }

    delete[] arr;

    if (result == -1) {
        cout << "\n  Borrower not found.\n"; pressEnter(); return;
    }

    Borrower& b = borrowers[result];

    cout << "\n";
    printHeader("SEARCH RESULT", 64);
    printRow("User ID  : " + b.userID,   64);
    printRow("Name     : " + b.fullName, 64);
    printRow("Username : " + b.username, 64);
    printRow("Contact  : " + b.contact,  64);
    printLine(64);

    if (b.sessionCount == 0) {
        printRow("No borrow sessions yet.", 64);
        printLine(64);
    } else {
        double grandTotal = 0, grandPaid = 0;

        for (int s = 0; s < b.sessionCount; s++) {
            BorrowSession& ses = b.sessions[s];
            cout << "\n";
            printHeader("BORROW SESSION #" + to_string(s + 1), 64);
            printRow("Date Borrowed : " + ses.date,    64);
            printRow("Due Date      : " + ses.dueDate, 64);
            printLine(64);

            cout << "  | " << pad("  ITEM NAME", 24)
                 << pad("QTY", 6)
                 << pad("PRICE", 14)
                 << pad("SUBTOTAL", 16) << " |\n";
            printLine(64);

            for (int i = 0; i < ses.itemCount; i++) {
                double sub = ses.items[i].quantity * ses.items[i].price;
                cout << "  | " << pad("  " + ses.items[i].name, 24)
                     << pad(to_string(ses.items[i].quantity), 6)
                     << pad("P" + dbl(ses.items[i].price), 14)
                     << pad("P" + dbl(sub), 16) << " |\n";
            }
            printLine(64);

            double bal = ses.total - ses.paid;
            printRow("Session Total  : P" + dbl(ses.total), 64);
            printRow("Amount Paid    : P" + dbl(ses.paid),  64);
            printRow("Remaining Bal  : P" + dbl(bal),       64);
            printLine(64);

            grandTotal += ses.total;
            grandPaid  += ses.paid;
        }

        cout << "\n";
        printHeader("GRAND SUMMARY", 64);
        printRow("Total Borrowed : P" + dbl(grandTotal),              64);
        printRow("Total Paid     : P" + dbl(grandPaid),               64);
        printRow("BALANCE OWED   : P" + dbl(grandTotal - grandPaid),  64);
        printLine(64);
    }

    pressEnter();
    borrowerActionMenu(result);
}

void addNewBorrower(int lenderIdx) {
    if (borrowerCount == borrowerCap) growBorrowers();

    Borrower& b = borrowers[borrowerCount];
    initBorrower(b);
    b.lenderIndex = lenderIdx;

    cout << "\n";
    printHeader("REGISTER NEW BORROWER", 54);

    while (true) {
        string uid = formatID(borrowerCount + 1);
        cout << "  Auto User ID: " << uid << "\n";
        cout << "  Use this ID? (1=Yes / 0=Enter custom): ";
        int opt = inputInt("");
        if (opt == 1) { b.userID = uid; break; }
        else if (opt == 0) {
            string cid = inputStr("  Enter custom ID (e.g. 00010): ");
            if (userIDExists(cid)) {
                cout << "  User ID already exists!\n"; continue;
            }
            b.userID = cid; break;
        }
        else cout << "  INVALID INPUT!!!\n";
    }

    b.fullName = inputStr("  Full Name   : ");
    b.contact  = inputStr("  Contact     : ");

    while (true) {
        b.username = inputStr("  Username    : ");
        if (usernameExists(b.username)) {
            cout << "  Username already taken! Try another.\n";
        } else break;
    }

    while (true) {
        string p1 = inputStr("  Password    : ");
        string p2 = inputStr("  Confirm Pass: ");
        if (p1 != p2) {
            cout << "  Passwords do not match! Try again.\n"; continue;
        }
        b.passHash = hashPass(p1, b.username);
        break;
    }

    borrowerCount++;

    cout << "\n";
    printHeader("BORROWER ACCOUNT CREATED", 54);
    printRow("User ID  : " + b.userID, 54);
    printRow("Username : " + b.username, 54);
    printRow("Name     : " + b.fullName, 54);
    printLine(54);

    cout << "  Add first borrow session now? (1=Yes / 0=No): ";
    int opt = inputInt("");
    if (opt == 1) addBorrowSession(borrowerCount - 1);
    else pressEnter();
}

void lenderDashboard(int idx) {
    bool on = true;
    while (on) {
        cout << "\n";
        printHeader("LENDER DASHBOARD  -  " + lenders[idx].storeName, 54);
        printRow("Owner : " + lenders[idx].fullName, 54);
        printLine(54);
        printRow("[1] Add New Borrower",  54);
        printRow("[2] See Due Dates",     54);
        printRow("[3] See All Borrowers", 54);
        printRow("[4] Search Borrower",   54);
        printRow("[0] Logout",            54);
        printLine(54);

        int c = inputInt("  Choice: ");
        if (c == 0) { on = false; cout << "  Logged out successfully.\n"; pressEnter(); }
        else if (c == 1) addNewBorrower(idx);
        else if (c == 2) seeDueDates(idx);
        else if (c == 3) seeAllBorrowers(idx);
        else if (c == 4) searchBorrower(idx);
        else cout << "  INVALID INPUT!!!\n";
    }
}

void borrowerDashboard(int bIdx) {
    displayBorrowerDetails(bIdx);
    pressEnter();
}

void lenderLogin() {
    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("LENDER LOGIN", 44);
        printRow("Press [0] to Cancel", 44);
        printLine(44);

        cout << "  Username: ";
        string u; getline(cin, u);
        if (u == "0") { back = true; break; }
        if (u == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        cout << "  Password: ";
        string p; getline(cin, p);
        if (p == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        string hashed = hashPass(p, u);
        bool found = false;
        for (int i = 0; i < lenderCount; i++) {
            if (lenders[i].username == u && lenders[i].passHash == hashed) {
                cout << "  Welcome, " << lenders[i].fullName << "!\n";
                pressEnter();
                lenderDashboard(i);
                found = true;
                back = true;
                break;
            }
        }
        if (!found && !back) {
            cout << "  Invalid username or password.\n";
        }
    }
}

void lenderRegister() {
    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("LENDER REGISTRATION", 54);
        printRow("Press [0] to Cancel", 54);
        printLine(54);

        cout << "  Full Name: ";
        string fn; getline(cin, fn);
        if (fn == "0") { back = true; break; }
        if (fn == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        cout << "  Store Name: ";
        string sn; getline(cin, sn);
        if (sn == "0") { back = true; break; }
        if (sn == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        cout << "  Contact: ";
        string ct; getline(cin, ct);
        if (ct == "0") { back = true; break; }
        if (ct == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        string uname = "";
        while (true) {
            cout << "  Username: ";
            getline(cin, uname);
            if (uname == "0") { back = true; break; }
            if (uname == "") { cout << "  INVALID INPUT!!!\n"; continue; }
            if (usernameExists(uname)) {
                cout << "  Username already taken! Try another.\n"; continue;
            }
            break;
        }
        if (back) break;

        string passHash = "";
        while (true) {
            cout << "  Password: ";
            string p1; getline(cin, p1);
            if (p1 == "0") { back = true; break; }
            if (p1 == "") { cout << "  INVALID INPUT!!!\n"; continue; }

            cout << "  Confirm    : ";
            string p2; getline(cin, p2);
            if (p2 == "") { cout << "  INVALID INPUT!!!\n"; continue; }

            if (p1 != p2) { cout << "  Passwords do not match!\n"; continue; }
            passHash = hashPass(p1, uname);
            break;
        }
        if (back) break;

        if (lenderCount == lenderCap) growLenders();
        lenders[lenderCount].fullName  = fn;
        lenders[lenderCount].storeName = sn;
        lenders[lenderCount].contact   = ct;
        lenders[lenderCount].username  = uname;
        lenders[lenderCount].passHash  = passHash;
        lenderCount++;

        cout << "\n  Registration successful! You may now log in.\n";
        pressEnter();
        back = true;
    }
}

void borrowerLogin() {
    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("BORROWER LOGIN", 44);
        printRow("Press [0] to Cancel", 44);
        printLine(44);

        cout << "  User ID: ";
        string uid; getline(cin, uid);
        if (uid == "0") { back = true; break; }
        if (uid == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        cout << "  Username : ";
        string u; getline(cin, u);
        if (u == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        cout << "  Password : ";
        string p; getline(cin, p);
        if (p == "") { cout << "  INVALID INPUT!!!\n"; continue; }

        string hashed = hashPass(p, u);
        bool found = false;
        for (int i = 0; i < borrowerCount; i++) {
            if (borrowers[i].userID   == uid &&
                borrowers[i].username == u   &&
                borrowers[i].passHash == hashed) {
                cout << "  Welcome, " << borrowers[i].fullName << "!\n";
                pressEnter();
                borrowerDashboard(i);
                found = true;
                back  = true;
                break;
            }
        }
        if (!found && !back) {
            cout << "  Invalid User ID, username, or password.\n";
        }
    }
}

void lenderMenu() {
    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("DEBTEASE  -  LENDER PORTAL", 44);
        printRow("[1] Login",    44);
        printRow("[2] Register", 44);
        printRow("[0] Back",     44);
        printLine(44);

        int c = inputInt("  Choice: ");
        if (c == 0) back = true;
        else if (c == 1) lenderLogin();
        else if (c == 2) lenderRegister();
        else cout << "  INVALID INPUT!!!\n";
    }
}

void borrowerMenu() {
    bool back = false;
    while (!back) {
        cout << "\n";
        printHeader("DEBTEASE  -  BORROWER PORTAL", 44);
        printRow("[1] Login", 44);
        printRow("[0] Back",  44);
        printLine(44);

        int c = inputInt("  Choice: ");
        if (c == 0) back = true;
        else if (c == 1) borrowerLogin();
        else cout << "  INVALID INPUT!!!\n";
    }
}

int main() {
    bool running = true;
    while (running) {
        cout << "\n";
        printHeader("DEBTEASE  -  DEBT MANAGEMENT SYSTEM", 54);
        printRow("  Localized Sari-Sari Store Ledger", 54);
        printLine(54);
        printRow("[1] Lender   (Store Owner)", 54);
        printRow("[2] Borrower (Customer)",    54);
        printRow("[0] Exit",                   54);
        printLine(54);

        int c = inputInt("  Choice: ");
        if (c == 0) {
            running = false;
            cout << "\n  Thank you for using DebtEase. Goodbye!\n";
        }
        else if (c == 1) lenderMenu();
        else if (c == 2) borrowerMenu();
        else cout << "  INVALID INPUT!!!\n";
    }

    delete[] lenders;
    delete[] borrowers;
    return 0;
}