#include <iostream>
#include <vector>
#include <new>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
int authorization(string username, string password) {
    ifstream file("password.txt");
    if (!file.is_open()) {
        cerr << "FAILED TO OPEN FILE" << endl;
        return 1;
    }
    string s_username, s_password;
    while (file >> s_username >> s_password) {
        if (s_username == username && s_password == password) {
            cout << "Login Successful" << endl;
            return 0;
        }
    }
    cout << "Invalid credentials" << endl;
    return 1;
}
string a_lowercase(string str) {
    for (char &c : str) {
        c = tolower(c);
    }
    return str;
}
string a_uppercase(string str) {
    for (char &c : str) {
        c = toupper(c);
    }
    return str;
}
void save_record(const string search) {
    
    ifstream infile("s_record.txt");
    if (!infile) {
        cerr << "FAILED TO OPEN FILE" << endl;
        return;
    }
    string line;
    bool found = false;
    // Open a new file to save the student details
    ofstream outfile("student_details.txt", ios::out); // Use ios::out to overwrite the file
    if (!outfile) {
        cerr << "FAILED TO CREATE OUTPUT FILE" << endl;
        return;
    }
    while (getline(infile, line)) {
        // Skip header and separator lines
        if (line.find("STUDENT NAME") != string::npos || line.find("--------") != string::npos) {
            continue;
        }
        stringstream iss(line);
        string name, matric;
        int cos1, cos2, mth, gst;
        float gpa;
        // Read the entire name (including spaces) up to the tab character
        size_t tabPos = line.find('\t');
        if (tabPos != string::npos) {
            name = line.substr(0, tabPos);
            line = line.substr(tabPos + 1); // Remove the name and tab from the line
        }
        // Use a new stringstream to parse the rest of the line
        stringstream rest(line);
        if (getline(rest, matric, '\t') && (rest >> cos1) && (rest >> cos2) && (rest >> mth) && (rest >> gst) && (rest >> gpa)) {
            if (search == matric) {
                found = true;
                // Print to terminal
                cout << "\nSTUDENT FOUND: \n";
                cout << "Name: " << name << endl;
                cout << "Matric Number: " << matric << endl;
                cout << "COS 201: " << cos1 << endl;
                cout << "COS 212: " << cos2 << endl;
                cout << "MATH 231: " << mth << endl;
                cout << "GST 201: " << gst << endl;
                cout << "GPA: " << gpa << endl;
                cout << "\n\n\nSaving to file......" << endl;
                // Write to the new file
                outfile << "\nSTUDENT FOUND: \n";
                outfile << "Name: " << name << endl;
                outfile << "Matric Number: " << matric << endl;
                outfile << "COS 201: " << cos1 << endl;
                outfile << "COS 212: " << cos2 << endl;
                outfile << "MATH 231: " << mth << endl;
                outfile << "GST 201: " << gst << endl;
                outfile << "GPA: " << gpa << endl;
                outfile << "\n\n\n";
                break; // Exit the loop once the student is found
            }
        }
    }
    if (!found) {
        cout << "NO AVAILABLE MATRIC NUMBER FOUND\n" << endl;
        outfile << "NO AVAILABLE MATRIC NUMBER FOUND\n" << endl;
    }
    infile.close();
    outfile.close();
}
void search_record(const string search) {
    ifstream infile("s_record.txt");
    if (!infile) {
        cerr << "FAILED TO OPEN FILE" << endl;
        return;
    }
    string line;
    bool found = false;
    while (getline(infile, line)) {
        if (line.find("STUDENT NAME") != string::npos || line.find("--------") != string::npos) {
            continue;
        }
        stringstream iss(line);
        string name, matric;
        int cos1, cos2, mth, gst;
        float gpa;
        // Read the entire name (including spaces) up to the tab character
        size_t tabPos = line.find('\t');
        if (tabPos != string::npos) {
            name = line.substr(0, tabPos);
            line = line.substr(tabPos + 1); // Remove the name and tab from the line
        }
        // Use a new stringstream to parse the rest of the line
        stringstream rest(line);
        if (getline(rest, matric, '\t') && (rest >> cos1) && (rest >> cos2) && (rest >> mth) && (rest >> gst) && (rest >> gpa)) {
            if (search == matric) {
                cout << "\nSTUDENT FOUND: \n";
                cout << "Name: " << name << endl;
                cout << "Matric Number: " << matric << endl;
                cout << "COS 201: " << cos1 << endl;
                cout << "COS 212: " << cos2 << endl;
                cout << "MATH 231: " << mth << endl;
                cout << "GST 201: " << gst << endl;
                cout << "GPA: " << gpa << endl;
                found = true;
                break;
            }
        }
    }
    if (!found) {
        cout << "NO AVAILABLE MATRIC NUMBER FOUND\n" << endl;
    }
    infile.close();
}
void update_record() {
    string search;
    cout << "ENTER STUDENT'S MATRIC NUMBER TO UPDATE: ";
    cin >> search;
    ifstream infile("s_record.txt");
    if (!infile) {
        cerr << "FAILED TO OPEN FILE" << endl;
        return;
    }
    // we pasted the entire record to a place in memory using vec
    vector<string> lines;
    string line;
    while (getline(infile, line)) {
        lines.push_back(line);
    }
    infile.close();
    bool found = false;
    // Open the file for writing (truncate the file)
    ofstream outfile("s_record.txt");
    if (!outfile) {
        cerr << "FAILED TO OPEN FILE FOR WRITING" << endl;
        return;
    }
    // Rewrite the file with updated records
    for (size_t i = 0; i < lines.size(); i++) {
        line = lines[i];
        // Skip header and separator lines
        if (line.find("STUDENT NAME") != string::npos || line.find("--------") != string::npos) {
            outfile << line << endl;
            continue;
        }
        stringstream iss(line);
        string name, matric;
        int cos1, cos2, mth, gst;
        float gpa;
        
        //i used AI to learn more on including spaces as i was getting error
        size_t tabPos = line.find('\t');
        if (tabPos != string::npos) {
            name = line.substr(0, tabPos);
            line = line.substr(tabPos + 1); // Remove the name and tab from the line
        }
        
        stringstream rest(line);
        if (getline(rest, matric, '\t') && (rest >> cos1) && (rest >> cos2) && (rest >> mth) && (rest >> gst) && (rest >> gpa)) {
            if (search == matric) {
                found = true;
                cout << "\nSTUDENT FOUND: \n";
                cout << "Name: " << name << endl;
                cout << "Matric Number: " << matric << endl;
                cout << "COS 201: " << cos1 << endl;
                cout << "COS 212: " << cos2 << endl;
                cout << "MATH 231: " << mth << endl;
                cout << "GST 201: " << gst << endl;
                cout << "GPA: " << gpa << endl;
                
                cout << "\nENTER NEW GRADES:\n";
                cout << "COS 201: ";
                cin >> cos1;
                cout << "COS 212: ";
                cin >> cos2;
                cout << "MATH 231: ";
                cin >> mth;
                cout << "GST 201: ";
                cin >> gst;
                cout << "GPA: ";
                cin >> gpa;
                
                outfile << name << "\t" << matric << "\t" << cos1 << "\t" << cos2 << "\t" << mth << "\t" << gst << "\t" << gpa << endl;
                cout << "RECORD UPDATED SUCCESSFULLY!\n";
            } else {
                
                
                outfile << name << "\t" << matric << "\t" << cos1 << "\t" << cos2 << "\t" << mth << "\t" << gst << "\t" << gpa << endl;
            }
        }
    }
    if (!found) {
        cout << "NO AVAILABLE MATRIC NUMBER FOUND\n" << endl;
    }
    outfile.close();
}
void display_all() {
    ifstream infile("s_record.txt");
    if (!infile) {
        cerr << "FAILED TO OPEN FILE" << endl;
        return;
    }
    string line;
    bool firstLine = true;
    cout << "\nDISPLAYING ALL STUDENT RECORDS:\n";
    cout << "--------------------------------------------\n";
    while (getline(infile, line)) {
        
        
        if (line.find("STUDENT NAME") != string::npos || line.find("--------") != string::npos) {
            if (firstLine) {
                cout << line << endl; 
                firstLine = false;
            }
            continue;
        }
        
        if (line.empty()) {
            continue;
        }
        stringstream iss(line);
        string name, matric;
        int cos1, cos2, mth, gst;
        float gpa;
        //Borrowed the search function and pasted to search and update
        size_t tabPos = line.find('\t');
        if (tabPos != string::npos) {
            name = line.substr(0, tabPos);
            line = line.substr(tabPos + 1); 
        }
        stringstream rest(line);
        if (getline(rest, matric, '\t') && (rest >> cos1) && (rest >> cos2) && (rest >> mth) && (rest >> gst) && (rest >> gpa)) {
            cout << "Name: " << name << endl;
            cout << "Matric Number: " << matric << endl;
            cout << "COS 201: " << cos1 << endl;
            cout << "COS 212: " << cos2 << endl;
            cout << "MATH 231: " << mth << endl;
            cout << "GST 201: " << gst << endl;
            cout << "GPA: " << gpa << endl;
            cout << "--------------------------------------------\n";
        } 
    }
    infile.close();
}
int main() {
    int authenticator;
    string username, password, input;
    string search;
    cout << "--------------------------------------------" << endl;
    cout << "  PAU RESULT MANAGEMENT SYSTEM (GROUP 2!)   " << endl;
    cout << "--------------------------------------------" << endl;
    while (true) {
        cout << "\n\nEnter your credentials? (y/n)";
        string start;
        getline(cin, start);
        if (start == "n" || start == "N") {
            cout << "Program is coming to an end " << endl;
            return 0;
        } else if (start == "y" || start == "Y") {
            system("cls");
            cout << "Lets proceed!\n\n\n";
            break;
        } else {
            cout << "Please enter a valid input y or n" << endl;
        }
    }
    do {
        cout << "Enter username : ";
        getline(cin, username);
        cout << "Enter password for " << username << ":";
        getline(cin, password);
        authenticator = authorization(username, password);
    } while (authenticator != 0);
    if (authenticator == 0) {
        do {
            cout << "\tMAIN MENU\nTO SEARCH FOR STUDENTS RESULT ENTER Q\nTO UPDATE A STUDENTS RESULT ENTER U\nTO SAVE A STUDENT RESULT TO A FILE ENTER P\nTO VIEW ALL RESULT ENTER A\nTO EXIT THE PROGRAM ENTER E\nENTER AN OPTION\n";
            cin >> input;
            cin.ignore();  // Clear the newline character left in the input buffer
            if (input == "p") {
                cout << "PRINT RESULT FILE" << endl;
                save_record(search);
            } else if (input == "q" || input == "Q") {
                cout << "SEARCH RECORD" << endl;
                cout << "ENTER STUDENTS MATRIC NUMBER\n";
                cin >> search;
                search_record(search);
            } else if (input == "a" || input == "A") {
                display_all();
            } else if (input == "u" || input == "U") {
                update_record();
            } else if (input == "e") {
                break;
            }
    }
			while (input != "e");
    return 0;
}}