//********************************************************
// 
// Assignment 7 - Employee Pay Calculator with Character Strings
// 
// Name: Felix Henriquez
// 
// Class: C Programming, Fall 2025
// 
// Date: November 2, 2025
// 
// Description: Extended employee pay calculator using structures,
//              character strings, and tax calculations to determine
//              state tax, federal tax, and net pay with summary stats.
// 
//********************************************************
 
#include <stdio.h>
#include <string.h>
 
// Constants for array sizes and business rules
#define MAX_EMPLOYEES 5
#define FIRST_NAME_SIZE 11  // 10 characters + null terminator
#define LAST_NAME_SIZE 11   // 10 characters + null terminator
#define TAX_STATE_SIZE 3    // 2 characters + null terminator
#define STANDARD_WORK_WEEK 40.0
#define OVERTIME_RATE 1.5
#define FED_TAX_RATE 0.25
 
// Structure for employee name
struct name
{
    char firstName[FIRST_NAME_SIZE];
    char lastName[LAST_NAME_SIZE];
};
 
// Structure for employee data
struct employee
{
    struct name empName;
    char taxState[TAX_STATE_SIZE];
    long int clockNumber;
    float wageRate;
    float hours;
    float overtimeHrs;
    float grossPay;
    float stateTax;
    float fedTax;
    float netPay;
};
 
// Structure for summary statistics
struct summaryStats
{
    float totalWage;
    float totalHours;
    float totalOvertimeHrs;
    float totalGrossPay;
    float totalStateTax;
    float totalFedTax;
    float totalNetPay;
 
    float avgWage;
    float avgHours;
    float avgOvertimeHrs;
    float avgGrossPay;
    float avgStateTax;
    float avgFedTax;
    float avgNetPay;
 
    float minWage;
    float minHours;
    float minOvertimeHrs;
    float minGrossPay;
    float minStateTax;
    float minFedTax;
    float minNetPay;
 
    float maxWage;
    float maxHours;
    float maxOvertimeHrs;
    float maxGrossPay;
    float maxStateTax;
    float maxFedTax;
    float maxNetPay;
};
 
/*****************************************************************************
 * Function: findMin
 * 
 * Purpose: Returns the minimum of two float values
 * 
 * Parameters: a - first value to compare
 *             b - second value to compare
 * 
 * Returns: The smaller of the two values
 *****************************************************************************/
float findMin(float a, float b) {
    return (a < b) ? a : b;
}
 
/*****************************************************************************
 * Function: findMax
 * 
 * Purpose: Returns the maximum of two float values
 * 
 * Parameters: a - first value to compare
 *             b - second value to compare
 * 
 * Returns: The larger of the two values
 *****************************************************************************/
float findMax(float a, float b) {
    return (a > b) ? a : b;
}
 
/*****************************************************************************
 * Function: getStateTaxRate
 * 
 * Purpose: Determines the state tax rate based on the state code
 * 
 * Parameters: state - two-character state code string
 * 
 * Returns: State tax rate as a float percentage
 *****************************************************************************/
float getStateTaxRate(const char state[]) {
    if (strcmp(state
, "MA") == 0) return 0.05;    // Massachusetts: 5%     if (strcmp(state
, "NH") == 0) return 0.00;    // New Hampshire: 0%     if (strcmp(state
, "VT") == 0) return 0.06;    // Vermont: 6%     if (strcmp(state
, "CA") == 0) return 0.07;    // California: 7%     return 0.08;                                  // All other states: 8%
}
 
/*****************************************************************************
 * Function: initializeEmployees
 * 
 * Purpose: Initializes the employee array with predefined data
 * 
 * Parameters: employees - array of employee structures to initialize
 * 
 * Returns: void
 *****************************************************************************/
void initializeEmployees(struct employee employees[]) {
    // Employee 1: Connie Cobol
    strcpy(employees
[0].
empName.
firstName, "Connie");     strcpy(employees
[0].
empName.
lastName, "Cobol");     strcpy(employees
[0].
taxState, "MA");     employees[0].clockNumber = 98401;
    employees[0].wageRate = 10.60;
 
    // Employee 2: Mary Apl
    strcpy(employees
[1].
empName.
firstName, "Mary");     strcpy(employees
[1].
empName.
lastName, "Apl");     strcpy(employees
[1].
taxState, "NH");     employees[1].clockNumber = 526488;
    employees[1].wageRate = 9.75;
 
    // Employee 3: Frank Fortran
    strcpy(employees
[2].
empName.
firstName, "Frank");     strcpy(employees
[2].
empName.
lastName, "Fortran");     strcpy(employees
[2].
taxState, "VT");     employees[2].clockNumber = 765349;
    employees[2].wageRate = 10.50;
 
    // Employee 4: Jeff Ada
    strcpy(employees
[3].
empName.
firstName, "Jeff");     strcpy(employees
[3].
empName.
lastName, "Ada");     strcpy(employees
[3].
taxState, "NY");     employees[3].clockNumber = 34645;
    employees[3].wageRate = 12.25;
 
    // Employee 5: Anton Pascal
    strcpy(employees
[4].
empName.
firstName, "Anton");     strcpy(employees
[4].
empName.
lastName, "Pascal");     strcpy(employees
[4].
taxState, "CA");     employees[4].clockNumber = 127615;
    employees[4].wageRate = 8.35;  // Corrected from 10.00 to 8.35
 
    // Initialize calculated fields to zero
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        employees[i].hours = 0;
        employees[i].overtimeHrs = 0;
        employees[i].grossPay = 0;
        employees[i].stateTax = 0;
        employees[i].fedTax = 0;
        employees[i].netPay = 0;
    }
}
 
/*****************************************************************************
 * Function: getEmployeeHours
 * 
 * Purpose: Reads hours worked for each employee from standard input
 * 
 * Parameters: employees - array of employee structures
 * 
 * Returns: void
 *****************************************************************************/
void getEmployeeHours(struct employee employees[]) {
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        scanf("%f", &employees
[i
].
hours);     }
}
 
/*****************************************************************************
 * Function: computeOvertime
 * 
 * Purpose: Calculates overtime hours for each employee
 * 
 * Parameters: employees - array of employee structures
 * 
 * Returns: void
 *****************************************************************************/
void computeOvertime(struct employee employees[]) {
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        if(employees[i].hours > STANDARD_WORK_WEEK) {
            employees[i].overtimeHrs = employees[i].hours - STANDARD_WORK_WEEK;
        } else {
            employees[i].overtimeHrs = 0.0;
        }
    }
}
 
/*****************************************************************************
 * Function: computeGrossPay
 * 
 * Purpose: Calculates gross pay including overtime at time-and-a-half
 * 
 * Parameters: employees - array of employee structures
 * 
 * Returns: void
 *****************************************************************************/
void computeGrossPay(struct employee employees[]) {
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        float regularHours = employees[i].hours;
        if(regularHours > STANDARD_WORK_WEEK) {
            regularHours = STANDARD_WORK_WEEK;
        }
        employees[i].grossPay = (regularHours * employees[i].wageRate) + 
                               (employees[i].overtimeHrs * employees[i].wageRate * OVERTIME_RATE);
    }
}
 
/*****************************************************************************
 * Function: computeTaxesAndNetPay
 * 
 * Purpose: Calculates state tax, federal tax, and net pay for each employee
 * 
 * Parameters: employees - array of employee structures
 * 
 * Returns: void
 *****************************************************************************/
void computeTaxesAndNetPay(struct employee employees[]) {
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        float stateRate = getStateTaxRate(employees[i].taxState);
        employees[i].stateTax = employees[i].grossPay * stateRate;
        employees[i].fedTax = employees[i].grossPay * FED_TAX_RATE;
        employees[i].netPay = employees[i].grossPay - employees[i].stateTax - employees[i].fedTax;
    }
}
 
/*****************************************************************************
 * Function: calculateSummaryStats
 * 
 * Purpose: Calculates comprehensive summary statistics for all employees
 * 
 * Parameters: employees - array of employee structures
 *             stats - pointer to summaryStats structure to store results
 * 
 * Returns: void
 *****************************************************************************/
void calculateSummaryStats(struct employee employees[], struct summaryStats *stats) {
    // Initialize totals to zero
    stats->totalWage = 0;
    stats->totalHours = 0;
    stats->totalOvertimeHrs = 0;
    stats->totalGrossPay = 0;
    stats->totalStateTax = 0;
    stats->totalFedTax = 0;
    stats->totalNetPay = 0;
 
    // Initialize min values with first employee's data
    stats->minWage = employees[0].wageRate;
    stats->minHours = employees[0].hours;
    stats->minOvertimeHrs = employees[0].overtimeHrs;
    stats->minGrossPay = employees[0].grossPay;
    stats->minStateTax = employees[0].stateTax;
    stats->minFedTax = employees[0].fedTax;
    stats->minNetPay = employees[0].netPay;
 
    // Initialize max values with first employee's data
    stats->maxWage = employees[0].wageRate;
    stats->maxHours = employees[0].hours;
    stats->maxOvertimeHrs = employees[0].overtimeHrs;
    stats->maxGrossPay = employees[0].grossPay;
    stats->maxStateTax = employees[0].stateTax;
    stats->maxFedTax = employees[0].fedTax;
    stats->maxNetPay = employees[0].netPay;
 
    // Calculate totals and find min/max values
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        // Calculate totals
        stats->totalWage += employees[i].wageRate;
        stats->totalHours += employees[i].hours;
        stats->totalOvertimeHrs += employees[i].overtimeHrs;
        stats->totalGrossPay += employees[i].grossPay;
        stats->totalStateTax += employees[i].stateTax;
        stats->totalFedTax += employees[i].fedTax;
        stats->totalNetPay += employees[i].netPay;
 
        // Find minimum values
        stats->minWage = findMin(stats->minWage, employees[i].wageRate);
        stats->minHours = findMin(stats->minHours, employees[i].hours);
        stats->minOvertimeHrs = findMin(stats->minOvertimeHrs, employees[i].overtimeHrs);
        stats->minGrossPay = findMin(stats->minGrossPay, employees[i].grossPay);
        stats->minStateTax = findMin(stats->minStateTax, employees[i].stateTax);
        stats->minFedTax = findMin(stats->minFedTax, employees[i].fedTax);
        stats->minNetPay = findMin(stats->minNetPay, employees[i].netPay);
 
        // Find maximum values
        stats->maxWage = findMax(stats->maxWage, employees[i].wageRate);
        stats->maxHours = findMax(stats->maxHours, employees[i].hours);
        stats->maxOvertimeHrs = findMax(stats->maxOvertimeHrs, employees[i].overtimeHrs);
        stats->maxGrossPay = findMax(stats->maxGrossPay, employees[i].grossPay);
        stats->maxStateTax = findMax(stats->maxStateTax, employees[i].stateTax);
        stats->maxFedTax = findMax(stats->maxFedTax, employees[i].fedTax);
        stats->maxNetPay = findMax(stats->maxNetPay, employees[i].netPay);
    }
 
    // Calculate averages
    stats->avgWage = stats->totalWage / MAX_EMPLOYEES;
    stats->avgHours = stats->totalHours / MAX_EMPLOYEES;
    stats->avgOvertimeHrs = stats->totalOvertimeHrs / MAX_EMPLOYEES;
    stats->avgGrossPay = stats->totalGrossPay / MAX_EMPLOYEES;
    stats->avgStateTax = stats->totalStateTax / MAX_EMPLOYEES;
    stats->avgFedTax = stats->totalFedTax / MAX_EMPLOYEES;
    stats->avgNetPay = stats->totalNetPay / MAX_EMPLOYEES;
}
 
/*****************************************************************************
 * Function: displayReport
 * 
 * Purpose: Displays the complete payroll report with summary statistics
 * 
 * Parameters: employees - array of employee structures
 * 
 * Returns: void
 *****************************************************************************/
void displayReport(struct employee employees[]) {
    struct summaryStats stats;
    calculateSummaryStats(employees, &stats);
 
    printf("\n*** Pay Calculator ***\n");     printf("---------------------------------------------------------------------------------\n");     printf("Name                Tax  Clock#  Wage   Hours  OT   Gross   State  Fed      Net\n");     printf("                    State                           Pay     Tax    Tax      Pay\n");     printf("---------------------------------------------------------------------------------\n");  
    for(int i = 0; i < MAX_EMPLOYEES; i++) {
        char fullName[25];  // Buffer for full name display
        sprintf(fullName
, "%s %s", employees
[i
].
empName.
firstName, employees
[i
].
empName.
lastName);  
        printf("%-18s %-3s %06ld  %5.2f  %5.1f  %4.1f  %7.2f  %5.2f  %6.2f  %7.2f\n",                fullName,
               employees[i].taxState,
               employees[i].clockNumber,
               employees[i].wageRate,
               employees[i].hours,
               employees[i].overtimeHrs,
               employees[i].grossPay,
               employees[i].stateTax,
               employees[i].fedTax,
               employees[i].netPay);
    }
 
    printf("---------------------------------------------------------------------------------\n");     printf("Totals:                         %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n",            stats.totalWage, stats.totalHours, stats.totalOvertimeHrs,
           stats.totalGrossPay, stats.totalStateTax, stats.totalFedTax, stats.totalNetPay);
    printf("Averages:                       %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n",            stats.avgWage, stats.avgHours, stats.avgOvertimeHrs,
           stats.avgGrossPay, stats.avgStateTax, stats.avgFedTax, stats.avgNetPay);
    printf("Minimum:                        %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n",            stats.minWage, stats.minHours, stats.minOvertimeHrs,
           stats.minGrossPay, stats.minStateTax, stats.minFedTax, stats.minNetPay);
    printf("Maximum:                        %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n",            stats.maxWage, stats.maxHours, stats.maxOvertimeHrs,
           stats.maxGrossPay, stats.maxStateTax, stats.maxFedTax, stats.maxNetPay);
}
 
/*****************************************************************************
 * Function: main
 * 
 * Purpose: Program entry point - orchestrates the payroll calculation process
 * 
 * Parameters: none
 * 
 * Returns: int - program exit status
 *****************************************************************************/
int main() {
    struct employee employees[MAX_EMPLOYEES];  // Array of employee structures
 
    // Execute payroll processing steps
    initializeEmployees(employees);
    getEmployeeHours(employees);
    computeOvertime(employees);
    computeGrossPay(employees);
    computeTaxesAndNetPay(employees);
    displayReport(employees);
 
    return 0;
}