#include <iostream>
#include <string>
#include <vector>

using namespace std;

// Define the base class Person
class Person {
protected:
    string name;
    string address;
    string phone;

public:
    // Constructor for Person class
    Person(const string& n, const string& addr, const string& ph)
        : name(n), address(addr), phone(ph) {}

    // Virtual function to display person information
    virtual void displayInfo() const {
        cout << "Name: " << name << endl;
        cout << "Address: " << address << endl;
        cout << "Phone: " << phone << endl;
    }

    // Getter for name attribute
    string getName() const { return name; }
};

// Define the Car class
class Car {
private:
    static int nextCarID;
    int carID;
    string make;
    string model;
    double price;
    bool isAvailable = true;

public:
    // Constructor for Car class
    Car(const string& mk, const string& mdl, double pr)
        : carID(nextCarID++), make(mk), model(mdl), price(pr), isAvailable(true) {}

    // Function to display car information
    void displayInfo() const {
        cout << "Car ID: " << carID << endl;
        cout << "Make: " << make << endl;
        cout << "Model: " << model << endl;
        cout << "Price: £" << price << endl;
        cout << "Available: " << (isAvailable ? "Yes" : "No") << endl;
    }

    // Getter for isAvailable attribute 
    bool getIsAvailable() const { return isAvailable; }

    // Function to mark the car as sold
    void sellCar() { isAvailable = false; }

    // Getter for carID attribute
    int getCarID() const { return carID; }

    // Getter for make attribute
    string getMake() const { return make; }

    // Getter for model attribute
    string getModel() const { return model; }
};

int Car::nextCarID = 1;

// Define the Customer class that inherits from Person
class Customer : public Person {
private:
    static int nextCustomerID;
    int customerID;

public:
    // Constructor for Customer class
    Customer(const string& n, const string& addr, const string& ph)
        : Person(n, addr, ph), customerID(nextCustomerID++) {}

    // Function to display customer information
    void displayInfo() const override {
        Person::displayInfo();
        cout << "Customer ID: " << customerID << endl;
    }

    // Function for a customer to buy a car
    void buyCar(Car& car) {
        if (car.getIsAvailable()) {
            car.sellCar();
            cout << getName() << " has purchased the car: " << car.getMake() << " " << car.getModel() << endl;
        } else {
            cout << "Sorry, this car is not available." << endl;
        }
    }

    // Getter for customerID attribute
    int getCustomerID() const { return customerID; }
};

int Customer::nextCustomerID = 1;


// Define the CarSalesSystem class
class CarSalesSystem {
private:
    vector<Car> cars;
    vector<Customer> customers;

public:
    // Function to add a new car to the system
void addCar() {
    string make, model;
    double price;

    // Clear the input buffer to avoid reading leftover newline characters
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    // Input validation loop for make
    while (true) {
        cout << "Enter Car Make: ";
        getline(cin, make);

        if (!make.empty()) {
            break;
        } else {
            cout << "Make cannot be empty. Please enter a valid make." << endl;
        }
    }

    // Input validation loop for model
    while (true) {
        cout << "Enter Car Model: ";
        getline(cin, model);

        if (!model.empty()) {
            break;
        } else {
            cout << "Model cannot be empty. Please enter a valid model." << endl;
        }
    }

    // Input validation loop for price (not negative)
    do {
        cout << "Enter Car Price: ";
        cin >> price;

        if (price < 0) {
            cout << "Price cannot be negative. Please enter a valid price." << endl;
            cin.clear(); // Clear the error flag
            cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Clear the input buffer
        }
    } while (price < 0);

    // Ignore leftover newline after reading price
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    cars.emplace_back(make, model, price);
    cout << "Car added successfully." << endl;
}



    // Function to add a new customer to the system
void addCustomer() {
    string name, address, phone;

    // Clear the input buffer to avoid reading leftover newline characters
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    // Input validation for name
    while (true) {
        cout << "Enter Customer Name: ";
        getline(cin, name);
        if (!name.empty()) {
            break;
        } else {
            cout << "Name cannot be empty. Please enter a valid name." << endl;
        }
    }

    // Input validation for address
    while (true) {
        cout << "Enter Customer Address: ";
        getline(cin, address);
        if (!address.empty()) {
            break;
        } else {
            cout << "Address cannot be empty. Please enter a valid address." << endl;
        }
    }

    // Input validation for phone number
    while (true) {
        cout << "Enter Customer Phone: ";
        getline(cin, phone);
        if (!phone.empty()) {
            break;
        } else {
            cout << "Phone number cannot be empty. Please enter a valid phone number." << endl;
        }
    }

    customers.emplace_back(name, address, phone);
    cout << "Customer added successfully." << endl;
}



    // Function to display available cars in the system
    void displayCars() const {
        cout << "\nAvailable Cars:" << endl;
        for (const auto& car : cars) {
            if (car.getIsAvailable()) {
                car.displayInfo();
                cout << "------------------------" << endl;
            }
        }
    }

    // Function to find a customer by their ID
    Customer* findCustomerByID(int customerID) {
        for (auto& customer : customers) {
            if (customer.getCustomerID() == customerID) {
                return &customer;
            }
        }
        return nullptr;
    }

    // Function to allow a customer to buy a car
    void sellCar() {
        int carID, customerID;
        cout << "Enter Car ID to buy: ";
        cin >> carID;
        cout << "Enter your Customer ID: ";
        cin >> customerID;

        Car* car = nullptr;
        for (auto& c : cars) {
            if (c.getCarID() == carID && c.getIsAvailable()) {
                car = &c;
                break;
            }
        }

        Customer* customer = findCustomerByID(customerID);
        if (car && customer) {
            customer->buyCar(*car);
        } else {
            cout << "Invalid Car ID or Customer ID. "
                 << "Speak to a member of staff to create your account or verify the Car ID." << endl;
        }
    }

    // Function to display the staff menu
    void showStaffMenu() {
        int choice;
        do {
            cout << "\nStaff Menu" << endl;
            cout << "1. Add Car" << endl;
            cout << "2. Add Customer" << endl;
            cout << "3. View Cars" << endl;
            cout << "4. Back to Main Menu" << endl;
            cout << "Enter your choice: ";
            cin >> choice;

            switch (choice) {
                case 1:
                    addCar();
                    break;
                case 2:
                    addCustomer();
                    break;
                case 3:
                    displayCars();
                    break;
                case 4:
                    return;
                default:
                    cout << "Invalid choice. Please try again." << endl;
            }
        } while (true);
    }

    // Function to display the customer menu
    void showCustomerMenu() {
        int choice;
        do {
            cout << "\nCustomer Menu" << endl;
            cout << "1. View Cars" << endl;
            cout << "2. Buy Car" << endl;
            cout << "3. Back to Main Menu" << endl;
            cout << "Enter your choice: ";
            cin >> choice;

            switch (choice) {
                case 1:
                    displayCars();
                    break;
                case 2:
                    sellCar();
                    break;
                case 3:
                    return;
                default:
                    cout << "Invalid choice. Please try again." << endl;
            }
        } while (true);
    }
};

int main() {
    CarSalesSystem system;
    int choice;

    do {
        cout << "\nMain Menu" << endl;
        cout << "1. Staff Menu" << endl;
        cout << "2. Customer Menu" << endl;
        cout << "3. Exit" << endl;
        cout << "Enter your choice: ";
        cin >> choice;

        switch (choice) {
            case 1:
                system.showStaffMenu();
                break;
            case 2:
                system.showCustomerMenu();
                break;
            case 3:
                cout << "Exiting the system." << endl;
                break;
            default:
                cout << "Invalid choice. Please try again." << endl;
        }
    } while (choice != 3);

    return 0;
}
