#include <iostream>

#include <string>


using namespace std;


class Bill {

protected:

    int invoiceId;

    double totalAmount;

    double taxRate;

    string customerName;

    string paymentStatus;


public:

    Bill(int id, double amount, double rate, string name)

        : invoiceId(id), totalAmount(amount), taxRate(rate), customerName(name), paymentStatus("Pending") {}


    int getInvoiceId() const {

        return invoiceId;

    }


    double getTotalAmount() const {

        return totalAmount;

    }


    double getTaxRate() const {

        return taxRate;

    }


    virtual void displayDetails() {

        cout << "Invoice ID: " << invoiceId << endl;

        cout << "Customer: " << customerName << endl;

        cout << "Total Amount: " << totalAmount << endl;

        cout << "Tax Rate: " << taxRate << "%" << endl;

        cout << "Payment Status: " << paymentStatus << endl;

    }


    virtual void updatePaymentStatus(string status) {

        paymentStatus = status;

    }


    virtual double calculatePayment() {

        return totalAmount * (1 + (taxRate / 100));


    }

};


class BillManagementSystem {

private:

    static const int MAX_BILLS = 100;

    Bill* bills[MAX_BILLS];

    int numBills;


public:

    BillManagementSystem() : numBills(0) {}


    void addBill(Bill* bill) {

        if (numBills < MAX_BILLS) {

            bills[numBills++] = bill;

            cout << "Bill added successfully." << endl;

        } else {

            cout << "Bill limit reached. Cannot add more bills." << endl;

        }

    }


    void displayBills() {

        for (int i = 0; i < numBills; i++) {

            bills[i]->displayDetails();

            cout << endl;

        }

    }


    void updatePaymentStatus(int invoiceId, string newStatus) {

        for (int i = 0; i < numBills; i++) {

            if (bills[i]->getInvoiceId() == invoiceId) {

                bills[i]->updatePaymentStatus(newStatus);

                cout << "Payment status updated successfully." << endl;

                return;

            }

        }

        cout << "Bill not found." << endl;

    }


    void deleteBill(int invoiceId) {

        for (int i = 0; i < numBills; i++) {

            if (bills[i]->getInvoiceId() == invoiceId) {

                delete bills[i];

                bills[i] = bills[numBills - 1];

                numBills--;

                cout << "Bill deleted successfully." << endl;

                return;

            }

        }

        cout << "Bill not found." << endl;

    }


    void searchBillByInvoiceId(int invoiceId) {

        for (int i = 0; i < numBills; i++) {

            if (bills[i]->getInvoiceId() == invoiceId) {

                bills[i]->displayDetails();

                return;

            }

        }

        cout << "Bill not found." << endl;

    }


    void searchBillByTotalAmount(double amount) {

        cout << "Bills with Total Amount $" << amount << ":" << endl;

        for (int i = 0; i < numBills; i++) {

            if (bills[i]->getTotalAmount() == amount) {

                bills[i]->displayDetails();

                cout << endl;

            }

        }

    }


    void searchBillByTaxRate(double rate) {

        cout << "Bills with Tax Rate " << rate << "%:" << endl;

        for (int i = 0; i < numBills; i++) {

            if (bills[i]->getTaxRate() == rate) {

                bills[i]->displayDetails();

                cout << endl;

            }

        }

    }


    void generateReports() {

        double totalBillAmount = 0.0;

        double totalTaxPaid = 0.0;


        cout << "Bill Reports" << endl;

        cout << "============" << endl;


        for (int i = 0; i < numBills; i++) {

            totalBillAmount += bills[i]->getTotalAmount();

            totalTaxPaid += bills[i]->calculatePayment() - bills[i]->getTotalAmount();

        }


        cout << "Total Number of Bills: " << numBills << endl;

        cout << "Total Bill Amount: " << totalBillAmount << endl;

        cout << "Total Tax Paid: " << totalTaxPaid << endl;

    }

};


int main() {

    BillManagementSystem system;


    while (true) {

        cout << "Billing Management System" << endl;

        cout << "1. Manage Bills" << endl;

        cout << "2. Search Bills" << endl;

        cout << "3. Reports of Bills" << endl;

        cout << "4. Exit" << endl;


        int choice;

        cin >> choice;


        switch (choice) {

        case 1: {

            cout << "1. Add Bills" << endl;

            cout << "2. Update Bills" << endl;

            cout << "3. Display Bills" << endl;

            cout << "4. Delete Bills" << endl;

            cout << "5. Exit" << endl;


            int subChoice;

            cin >> subChoice;


            switch (subChoice) {

            case 1: {

                int id;

                double amount, rate;

                string name;


                cout << "Enter Invoice ID: ";

                cin >> id;

                cout << "Enter Customer Name: ";

                cin.ignore();

                getline(cin, name);

                cout << "Enter Total Amount: ";

                cin >> amount;

                cout << "Enter Tax Rate: ";

                cin >> rate;


                Bill* newBill = new Bill(id, amount, rate, name);

                system.addBill(newBill);

                break;

            }

            case 2: {

                int invoiceId;

                string newStatus;

                cout << "Enter Invoice ID: ";

                cin >> invoiceId;

                cout << "Enter new payment status: ";

                cin.ignore();

                getline(cin, newStatus);

                system.updatePaymentStatus(invoiceId, newStatus);

                break;

            }

            case 3: {

                system.displayBills();

                break;

            }

            case 4: {

                int invoiceId;

                cout << "Enter Invoice ID to delete: ";

                cin >> invoiceId;

                system.deleteBill(invoiceId);

                break;

            }

            case 5:

                cout << "Returning to the main menu." << endl;

                break;

            default:

                cout << "Invalid choice. Please select a valid option." << endl;

            }

            break;

        }

        case 2: {

            cout << "1. Search by Invoice ID" << endl;

            cout << "2. Search by Total Amount" << endl;

            cout << "3. Search by Tax Rate" << endl;


            int searchSubChoice;

            cin >> searchSubChoice;


            switch (searchSubChoice) {

            case 1: {

                int invoiceId;

                cout << "Enter Invoice ID to search: ";

                cin >> invoiceId;

                system.searchBillByInvoiceId(invoiceId);

                break;

            }

            case 2: {

                double amount;

                cout << "Enter Total Amount to search: ";

                cin >> amount;

                system.searchBillByTotalAmount(amount);

                break;

            }

            case 3: {

                double rate;

                cout << "Enter Tax Rate to search: ";

                cin >> rate;

                system.searchBillByTaxRate(rate);

                break;

            }

            default:

                cout << "Invalid choice. Please select a valid option." << endl;

            }

            break;

        }

        case 3: {

            system.generateReports();

            break;

        }

        case 4:

            cout << "Exiting..." << endl;

            return 0;

        default:

            cout << "Invalid choice. Please select a valid option." << endl;

        }

    }


    return 0;

}