#include <iostream>
#include <string>
#include <vector>
#include <Windows.h>
#include <unordered_map>
#include <algorithm>
#include <iomanip>

using namespace std;

const int N = 1010;

class student
{
public:
    int index;

    void setName(const string &Name)
    {
        name = Name;
    }
    void setID(const string &id)
    {
        ID = id;
    }
    void setClassID(const string &clsid)
    {
        class_id = clsid;
    }
    void setCourse(int a, int b, int c, int d)
    {
        course[0] = a;
        course[1] = b;
        course[2] = c;
        course[3] = d;
    }
    void setDel(bool st)
    {
        deleted = st;
    }

    bool getDel()
    {
        return deleted;
    }
    double getSum()
    {
        sum = 0;
        for (int i = 0; i < 4; i++)
        {
            sum += course[i];
        }
        return sum;
    }
    void printInfo()
    {
        puts("该学生信息如下：");
        cout << "姓名：" << this->getName() << endl;
        cout << "学号：" << this->getID() << endl;
        cout << "班级：" << this->getClassID() << endl;
        cout << "四门成绩分别为：";
        for (int i = 0; i < 4; i++)
        {
            cout << course[i] << " ";
        }
    }
    string getName()
    {
        return name;
    }
    string getID()
    {
        return ID;
    }
    string getClassID()
    {
        return class_id;
    }

private:
    string ID;
    string name;
    string class_id;
    double course[4];
    double sum = 0;
    int rank;
    bool deleted = false;
};

int idx = 1;
vector<student> students(N);
unordered_map<std::string, int> studentsById;
unordered_map<std::string, int> studentsByName;

// 函数声明区域
// ———————————————————————————————service———————————————————————————
void addStudentInfo();
void findStudentInfo();
void sortBySum(int l, int r);
void modifyInfo(student &stu);
void deleteStudent(int del_idx);
// ———————————————————————————————service———————————————————————————

// ————————————————————————————————view——————————————————————————————
int getConsoleWidth();
void centerPrint(const string &text);
void showMenu();
void printRank();
void showModifyMenu();
// ————————————————————————————————view——————————————————————————————

//-----------------------------------------------------------------------------

int main()
{

    int op;
    while (1)
    {
        showMenu();
        cin >> op;

        switch (op)
        {
        case 1:
            // 添加学生
            addStudentInfo();
            break;

        case 2:
            // 查询学生
            findStudentInfo();
            break;

        case 3:
            // 显示排名
            sortBySum(0, idx);
            printRank();
            break;

        case 0:
            // 退出
            puts("请再按下回车键退出系统……");
            return 0;
            break;

        default:
            break;
        }
    }

    system("pause");
    return 0;
}

//-----------------------------------------------------------------------------

// 函数实现区域

// ———————————————————————————————service———————————————————————————

// 添加学生信息
void addStudentInfo()
{
    system("cls");

    puts("");
    puts("");
    puts("");
    puts("");
    centerPrint("录入学生信息");

    if (idx > N)
    {
        puts("长度超出预先设定范围，请重新设置预设长度");
        return;
    }

    students[idx].index = idx;

    cout << "请输入学生学号：";
    string id;
    cin >> id;
    students[idx].setID(id);
    studentsById[students[idx].getID()] = idx;
    puts("");

    cout << "请输入学生姓名：";
    string name;
    cin >> name;
    students[idx].setName(name);
    studentsByName[students[idx].getName()] = idx;
    puts("");

    cout << "请输入学生班级：";
    string cls;
    cin >> cls;
    students[idx].setClassID(cls);
    puts("");

    cout << "请输入学生四门课的成绩：";
    int temp[4];
    for (int i = 0; i < 4; i++)
    {
        cin >> temp[i];
    }
    students[idx].setCourse(temp[0], temp[1], temp[2], temp[3]);
    puts("");

    students[idx].setDel(false);

    students[idx].getSum(); // 保存总分

    idx++; // 数组下标调至下一位

    puts("添加完毕，继续添加(1) or 回到主菜单(0)？");
    int op;
    cin >> op;
    if (op == 1)
    {
        system("cls");
        addStudentInfo();
    }
    else if (op == 0)
    {
        system("cls");
    }
}

// 查询学生信息
void findStudentInfo()
{
    system("cls");

    puts("");
    puts("");
    puts("");
    puts("");
    centerPrint("查询学生信息");

    int op;
    cout << "请输入查找方式 按名字查找(0) or 按学号查找(1) :";
    cin >> op;
    if (op == 0) // 按名字查找
    {
        system("cls");

        puts("");
        puts("");
        puts("");
        puts("");
        centerPrint("查询学生信息");

        cout << "请输入学生姓名：";
        string nm;
        cin >> nm;

        auto itByName = studentsByName.find(nm);
        if (itByName != studentsByName.end())
        {
            int foundIndex = itByName->second;

            if (students[foundIndex].getDel() == true)
            {
                puts("该学生已被删除，要重新添加吗？[y/N]");
                char cho;
                cin >> cho;
                if (cho == 'y')
                {
                    addStudentInfo();
                }
                else
                {
                    return;
                }
            }
            students[foundIndex].printInfo();

            puts("");
            puts("");
            char op;
            cout << "需要修改或者删除他的信息吗？[y/N]:";
            cin >> op;
            if (op == 'N')
                return;
            else if (op == 'y')
            {
                puts("");
                int op;
                cout << "修改(0) or 删除(1) ?:";
                cin >> op;
                if (op == 0)
                {
                    showModifyMenu();
                    modifyInfo(students[foundIndex]);
                }
                else if (op == 1)
                {
                    deleteStudent(foundIndex);
                }
            }
        }
        else
        {
            puts("查无此人");
            cout << "要增加该学生的信息吗？[y/N]";
            char op;
            cin >> op;
            if (op == 'y')
            {
                addStudentInfo();
            }
            else if (op == 'N')
            {
                return;
            }
        }
    }
    else if (op == 1) // 按学号查找
    {
        system("cls");

        puts("");
        puts("");
        puts("");
        puts("");
        centerPrint("查询学生信息");

        cout << "请输入学生学号：";
        string id;
        cin >> id;

        auto itByID = studentsById.find(id);
        if (itByID != studentsById.end() && students[itByID->second].getDel() == false)
        {
            int foundIndex = itByID->second;

            if (students[foundIndex].getDel() == true)
            {
                puts("该学生已被删除，要重新添加吗？[y/N]");
                char cho;
                cin >> cho;
                if (cho == 'y')
                {
                    addStudentInfo();
                }
                else
                {
                    return;
                }
            }

            students[foundIndex].printInfo();

            puts("");
            puts("");
            char op;
            cout << "需要修改或者删除他的信息吗？[y/N]:";
            cin >> op;
            if (op == 'N')
                return;
            else if (op == 'y')
            {
                puts("");
                int op;
                cout << "修改(0) or 删除(1) ?:";
                cin >> op;
                if (op == 0)
                {
                    showModifyMenu();
                    modifyInfo(students[foundIndex]);
                }
                else if (op == 1)
                {
                    deleteStudent(foundIndex);
                }
            }
        }
        else
        {
            puts("查无此人");
            cout << "要增加该学生的信息吗？[y/N]";
            char op;
            cin >> op;
            if (op == 'y')
            {
                addStudentInfo();
            }
            else if (op == 'N')
            {
                return;
            }
        }
    }
}

// 按照总分排序
void sortBySum(int l, int r)
{
    if (l >= r)
        return; // 如果只有一个元素或没有元素则停止
    int i = l - 1, j = r + 1;
    double x = students[l + r >> 1].getSum(); // 确定两边和分界条件
    while (i < j)                             // i = j 时跳出
    {
        do
            i++;
        while (students[i].getSum() < x);
        do
            j--;
        while (students[j].getSum() > x);
        if (i < j)
            swap(students[i], students[j]);
    }
    sortBySum(l, j), sortBySum(j + 1, r); // 递归
}

// 修改学生信息
void modifyInfo(student &stu)
{
    int op;
    cin >> op;
    switch (op)
    {
    case 1:
    { // 修改学号
        string id;
        cout << "请输入修改后的学号：";
        cin >> id;
        stu.setID(id);
        break;
    }

    case 2:
    { // 修改姓名
        string name;
        cout << "请输入修改后的姓名：";
        cin >> name;
        stu.setName(name);
        break;
    }

    case 3:
    { // 修改成绩
        cout << "请输入修改后的四门成绩：";
        double temp[4];
        for (int i = 0; i < 4; i++)
        {
            cin >> temp[i];
        }
        stu.setCourse(temp[0], temp[1], temp[2], temp[3]);
        break;
    }

    case 0:
        // 放弃修改
        return;
        break;

    default:
        break;
    }
    puts("");
    cout << "还要继续修改该学生的信息吗？[y/N]";
    char sel;
    cin >> sel;
    if (sel == 'y')
    {
        showModifyMenu();
        modifyInfo(stu);
    }
    else if (sel == 'N')
    {
        return;
    }
}

// 删除学生
void deleteStudent(int del_idx)
{
    // 首先标记该学生已删除（如果使用deleted字段）
    students[del_idx].setDel(true);

    // 从哈希表中删除该学生的信息
    studentsById.erase(students[del_idx].getID());
    studentsByName.erase(students[del_idx].getName());

    // 从向量中删除学生
    students.erase(students.begin() + del_idx);

    // 更新哈希表中的索引，减小所有后续学生的索引值
    for (auto &pair : studentsById)
    {
        if (pair.second > del_idx)
        {
            --pair.second;
        }
    }
    for (auto &pair : studentsByName)
    {
        if (pair.second > del_idx)
        {
            --pair.second;
        }
    }

    idx--; // 减少学生总数
}

// ———————————————————————————————service———————————————————————————
//------------------------------------------------------------------------------
// ————————————————————————————————view——————————————————————————————

// 获取控制台高度（用于居中输出文本）
int getConsoleWidth()
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    return csbi.srWindow.Right - csbi.srWindow.Left + 1;
}

// 居中输出文本(自定义输出)
void centerPrint(const string &text)
{
    int consoleWidth = getConsoleWidth();
    int textWidth = text.length();
    int padding = (consoleWidth - textWidth) / 2;

    for (int i = 0; i < padding; ++i)
    {
        cout << " ";
    }
    cout << text << endl;
}

// 开始菜单界面
void showMenu()
{
    system("cls");

    puts("");
    puts("");
    puts("");
    puts("");
    centerPrint("欢迎来到学生成绩管理系统");
    puts("");
    puts("");
    puts("");
    puts("");
    centerPrint("1. 录入学生信息");
    puts("");
    centerPrint("2. 查询学生信息");
    puts("");
    centerPrint("3. 显示成绩排名");
    puts("");
    centerPrint("0. 退出系统");
    puts("");
    puts("");
    puts("");
    puts("");
    puts("请按照编号选择操作：");
}

// 显示修改页面
void showModifyMenu()
{
    system("cls");

    puts("");
    puts("");
    puts("");
    puts("");
    centerPrint("请选择需要修改的信息");
    puts("");
    puts("");
    puts("");
    puts("");
    centerPrint("1. 学号");
    puts("");
    centerPrint("2. 姓名");
    puts("");
    centerPrint("3. 成绩");
    puts("");
    centerPrint("0. 放弃修改");
    puts("");
    puts("");
    puts("");
    puts("");
    puts("请按照编号选择操作：");
}

// 按照总分降序输出
void printRank()
{
    system("cls");

    // 设置表头
    cout << left << setw(25) << "排名"
         << setw(25) << "ID"
         << setw(25) << "姓名"
         << setw(25) << "班级"
         << setw(25) << "总分"
         << endl;

    // 输出分隔线
    cout << setfill('-') << setw(100) << "" << setfill(' ') << endl;

    // 遍历学生数组，输出每个学生的信息
    for (int i = idx; i > 1; i--)
    {
        cout << setw(25) << idx - i + 1
             << setw(25) << students[i].getID()
             << setw(25) << students[i].getName()
             << setw(25) << students[i].getClassID()
             << setw(25) << students[i].getSum()
             << endl;
    }

    system("pause");
}

// ————————————————————————————————view——————————————————————————————