#include <stdio.h>
#include <string.h>

#define NUM_EMPL 5
#define STD_HOURS 40.0
#define OT_RATE 1.5
#define FED_TAX_RATE 0.25

struct name {
    char firstName[10];
    char lastName[10];
};

struct employee {
    struct name empName;
    char taxState[3];
    long int clockNumber;
    float wageRate, hours, overtimeHrs;
    float grossPay, stateTax, fedTax, netPay;
};

struct totals {
    float wage, hours, overtime, gross, stateTax, fedTax, net;
};

struct min_max {
    float min[7], max[7];
};

/* Simplified Function Prototypes */
void getHours(struct employee *emp_ptr, int size);
void calculatePay(struct employee *emp_ptr, int size);
void printEmp(struct employee *emp_ptr, int size);
void processStatistics(struct employee *emp_ptr, struct totals *t_ptr, struct min_max *mm_ptr, int size);

int main(void)
{
    struct employee employeeData[NUM_EMPL] = {
        { {"Connie", "Cobol"}, "MA", 98401, 10.60},
        { {"Mary", "Apl"}, "NH", 526488, 9.75 },
        { {"Frank", "Fortran"}, "VT", 765349, 10.50 },
        { {"Jeff", "Ada"}, "NY", 34645, 12.25 },
        { {"Anton", "Pascal"}, "CA", 127615, 8.35 }
    };
    
    struct totals employeeTotals = {0};
    struct min_max employeeMinMax = {0};

    struct employee *emp_ptr = employeeData;
    struct totals *emp_totals_ptr = &employeeTotals;
    struct min_max *emp_minMax_ptr = &employeeMinMax;

    getHours(emp_ptr, NUM_EMPL);
    calculatePay(emp_ptr, NUM_EMPL);
    
    printf("\n*** Pay Calculator ***\n");
    printEmp(emp_ptr, NUM_EMPL);
    processStatistics(emp_ptr, emp_totals_ptr, emp_minMax_ptr, NUM_EMPL);

    return 0;
}

void getHours(struct employee *emp_ptr, int size)
{
    for (int i = 0; i < size; i++, emp_ptr++) {
        printf("Enter hours for employee %06li: ", emp_ptr->clockNumber);
        if (scanf("%f", &emp_ptr->hours) != 1) {
            printf("Error reading input.\n");
        }
    }
}

void calculatePay(struct employee *emp_ptr, int size)
{
    for (int i = 0; i < size; i++, emp_ptr++) {
        float rate = 0.08;

        emp_ptr->overtimeHrs = (emp_ptr->hours > STD_HOURS) ? (emp_ptr->hours - STD_HOURS) : 0;
        emp_ptr->grossPay = ((emp_ptr->hours - emp_ptr->overtimeHrs) * emp_ptr->wageRate) +
                            (emp_ptr->overtimeHrs * emp_ptr->wageRate * OT_RATE);

        if (strcmp(emp_ptr->taxState, "MA") == 0)      rate = 0.05;
        else if (strcmp(emp_ptr->taxState, "NH") == 0) rate = 0.00;
        else if (strcmp(emp_ptr->taxState, "VT") == 0) rate = 0.06;
        else if (strcmp(emp_ptr->taxState, "CA") == 0) rate = 0.07;

        emp_ptr->stateTax = emp_ptr->grossPay * rate;
        emp_ptr->fedTax   = emp_ptr->grossPay * FED_TAX_RATE;
        emp_ptr->netPay   = emp_ptr->grossPay - emp_ptr->stateTax - emp_ptr->fedTax;
    }
}

void printEmp(struct employee *emp_ptr, int size)
{
    printf("---------------------------------------------------------------------------------\n");
    printf("%-20s %-5s %8s %7s %6s %6s %8s %8s %8s %8s\n",
           "Name", "State", "Clock#", "Wage", "Hours", "OT", "Gross", "StateTax", "FedTax", "NetPay");
    printf("---------------------------------------------------------------------------------\n");

    for (int i = 0; i < size; i++, emp_ptr++) {
        char fullName[21];
        snprintf(fullName, sizeof(fullName), "%s %s", emp_ptr->empName.firstName, emp_ptr->empName.lastName);

        printf("%-20s %-5s %08li %7.2f %6.1f %6.1f %8.2f %8.2f %8.2f %8.2f\n",
               fullName, emp_ptr->taxState, emp_ptr->clockNumber,
               emp_ptr->wageRate, emp_ptr->hours, emp_ptr->overtimeHrs,
               emp_ptr->grossPay, emp_ptr->stateTax, emp_ptr->fedTax, emp_ptr->netPay);
    }
}

/* Combines calculation and printing logic cleanly using simple index looping */
void processStatistics(struct employee *emp_ptr, struct totals *t_ptr, struct min_max *mm_ptr, int size)
{
    // Initialize min and max values with the first employee's values
    float structural_vals[7] = {
        emp_ptr->wageRate, emp_ptr->hours, emp_ptr->overtimeHrs, 
        emp_ptr->grossPay, emp_ptr->stateTax, emp_ptr->fedTax, emp_ptr->netPay
    };
    for (int j = 0; j < 7; j++) {
        mm_ptr->min[j] = structural_vals[j];
        mm_ptr->max[j] = structural_vals[j];
    }

    // Accumulate total metrics and track min/max scales across all records
    for (int i = 0; i < size; i++) {
        struct employee *c = emp_ptr + i;
        float row[7] = { c->wageRate, c->hours, c->overtimeHrs, c->grossPay, c->stateTax, c->fedTax, c->netPay };
        
        t_ptr->wage     += c->wageRate;     t_ptr->hours    += c->hours;
        t_ptr->overtime += c->overtimeHrs;  t_ptr->gross    += c->grossPay;
        t_ptr->stateTax += c->stateTax;     t_ptr->fedTax   += c->fedTax;
        t_ptr->net      += c->netPay;

        for (int j = 0; j < 7; j++) {
            if (row[j] < mm_ptr->min[j]) mm_ptr->min[j] = row[j];
            if (row[j] > mm_ptr->max[j]) mm_ptr->max[j] = row[j];
        }
    }

    // Print summary blocks cleanly using our streamlined struct arrays
    printf("---------------------------------------------------------------------------------\n");
    printf("%-20s %-5s %8s %7.2f %6.1f %6.1f %8.2f %8.2f %8.2f %8.2f\n", "Totals:", "", "",
           t_ptr->wage, t_ptr->hours, t_ptr->overtime, t_ptr->gross, t_ptr->stateTax, t_ptr->fedTax, t_ptr->net);
    
    printf("%-20s %-5s %8s %7.2f %6.1f %6.1f %8.2f %8.2f %8.2f %8.2f\n", "Averages:", "", "",
           t_ptr->wage / size, t_ptr->hours / size, t_ptr->overtime / size, t_ptr->gross / size, t_ptr->stateTax / size, t_ptr->fedTax / size, t_ptr->net / size);
    
    printf("%-20s %-5s %8s %7.2f %6.1f %6.1f %8.2f %8.2f %8.2f %8.2f\n", "Minimum:", "", "",
           mm_ptr->min[0], mm_ptr->min[1], mm_ptr->min[2], mm_ptr->min[3], mm_ptr->min[4], mm_ptr->min[5], mm_ptr->min[6]);
    
    printf("%-20s %-5s %8s %7.2f %6.1f %6.1f %8.2f %8.2f %8.2f %8.2f\n", "Maximum:", "", "",
           mm_ptr->max[0], mm_ptr->max[1], mm_ptr->max[2], mm_ptr->max[3], mm_ptr->max[4], mm_ptr->max[5], mm_ptr->max[6]);
}