#include <stdio.h> // Include stdio.h for basic functions
#include <math.h> // Include math.h for round()
#include <stdlib.h> // Include stdlib.h for exit()

void CheckStatusForErrors(int status) { // Check user-inputted status varibale for values other than 0, 1, and 2
    if (status != 0 && status != 1 && status != 2) { // If status isn't equal to 0, 1, or 2
        printf("Error: Must input status 0 (dependent), 1 (single), or 2 (married).\n"); // Print error message
        exit(1); // End program early
    }
}

void CheckTaxesWithheldForErrors(int taxesWithheld) { // Check user-inputted taxesWithheld variable for negative values
    if (taxesWithheld < 0) { // If taxesWithheld is less than 0
        printf("Error: taxes withheld cannot be less than 0.\n"); // Print error message
        exit(1); // End program early
    }
}

int CalcAGI(int wages, int taxableInterest, int unemploymentCompensation) { // Calculate AGI
    int AGI = wages + taxableInterest + unemploymentCompensation; // AGI equals the sum of wages, taxableInterest, and unemploymentCompensation
    return AGI; // Return AGI when function is called
}

int GetDeduction(int status) { // Calculate tax deduction
    int deduction = 0; // Declare and initialize deduction as zero
    if (status == 0) { // If status is 0 (dependent)
        deduction = 6000; // Set deduction to 6000
    } else if (status == 1) { // If status is 1 (single)
        deduction = 12000; // Set deduction to 12000
    } else if (status == 2) { // If status is 2 (married)
        deduction = 24000; // Set deduction to 24000
    }
    return deduction; // Return deduction when function is called
}

int CalcTaxable(int AGI, int deduction) { // Calculate taxable income
    int taxableIncome = AGI - deduction; // taxableIncome equals AGI minus deduction
    if (taxableIncome < 0) { // If taxableIncome is negative
        taxableIncome = 0; // Set taxableIncome to zero
    }
    return taxableIncome; // Return taxableIncome when function is called
}

int CalcTax(int status, int taxableIncome) { // Calculate federal tax
    double federalTax = 0.0; // Declare and initialize federalTax as zero
    if (status == 0 || status == 1) { // If status is 0 (dependent) or 1 (sing;e)
        if (taxableIncome <= 10000) { // If taxableIncome is less than or equal to 10000
            federalTax = taxableIncome * 0.10; // Set federalTax to 10% of taxableIncome
        } else if (taxableIncome > 10000 && taxableIncome <= 40000) { // If taxableIncome is greater than 10000 and less than or equal to 40000
            federalTax = 1000 + ((taxableIncome - 10000) * 0.12); // Set federalTax to the sum of 1000 plus 12% of the taxableIncome over 10000
        } else if (taxableIncome > 40000 && taxableIncome <= 85000) { // If taxableIncome is greater than 40000 and less than or equal to 85000
            federalTax = 4600 + ((taxableIncome - 40000) * 0.22); // Set federalTax to the sum of 4600 plus 22% of the taxableIncome over 40000
        } else if (taxableIncome > 85000) { // If taxableIncome is greater than 85000
            federalTax = 14500 + ((taxableIncome - 85000) * 0.24); // Set federalTax to the sum of 14500 plus 24% of the taxableIncome over 85000
        }
    } else {
        if (taxableIncome <= 20000) { // If taxableIncome is less than or equal to 20000
            federalTax = taxableIncome * 0.10; // Set federalTax to 10% of taxableIncome
        } else if (taxableIncome > 20000 && taxableIncome <= 80000) { // If taxableIncome is greater than 20000 and less than or equal to 80000
            federalTax = 2000 + ((taxableIncome - 20000) * 0.12); // Set federalTax to the sum of 2000 plus 12% of the taxableIncome over 20000
        } else if (taxableIncome > 80000) { // If taxableIncome is greater than 80000
            federalTax = 9200 + ((taxableIncome - 80000) * 0.22); // Set federalTax to the sum of 9200 plus 22% of the taxableIncome over 80000
        }
    }
    int federalTaxRounded = round(federalTax); // Declare and initialize federalTaxRounded as the nearest whole number of federalTax
    return federalTaxRounded; // Return federalTaxRounded when function is called
}

int CalcTaxDue(int federalTax, int taxesWithheld) { // Calculate taxes still due
    int taxStillDue = federalTax - taxesWithheld; // Declare and initialize taxStillDue as federalTax minus taxesWithheld
    return taxStillDue; // Return taxStillDue when function is called
}

void CheckOwedOrRefund(int taxStillDue) { // Check if taxStillDue results in taxes owed or a tax refund
    if (taxStillDue < 0) { // If taxStillDue is negative
        printf("Tax Refund: $%d\n", taxStillDue * -1); // Print "tax refund" plus the positive of taxStillDue
    } else { // If taxStillDue is positive or 0
        printf("Taxes Owed: $%d\n", taxStillDue); // Print "taxes owed" plus the value of taxStillDue
    }
}

int main(void) { // Start main function

    int wages; // Declare wages
    int taxableInterest; // Declare taxableInterest
    int unemploymentCompensation; // Declare unemploymentCompensation
    
    printf("Please enter wages, taxable interest, and unemployment compensation: \n"); // Prompt for wages, taxable interest, and unemployment compensation
    scanf("%d", &wages); // Store user input for wages
    scanf("%d", &taxableInterest); // Store user input for taxableInterest
    scanf("%d", &unemploymentCompensation); // Store user input for unemploymentCompensation

    int status; // Declare status
    printf("Please enter status (0 dependent, 1 single, 2 married): \n"); // Prompt for status
    scanf("%d", &status); // Store user input for status
    CheckStatusForErrors(status); // Check status against 0, 1, or 2 and possibly return error

    int taxesWithheld; // Declare taxesWithheld
    printf("Please enter taxes withheld: \n"); // Prompt for taxes withheld
    scanf("%d", &taxesWithheld); // Store user input for taxesWithheld
    CheckTaxesWithheldForErrors(taxesWithheld); // Check taxesWithheld for negative values and possibly return error

    int AGI = CalcAGI(wages, taxableInterest, unemploymentCompensation); // Declare and initialize AGI as the returned value from CalcAGI()
    printf("AGI: $%d\n", AGI); // Print AGI

    int deduction = GetDeduction(status); // Declare and initialize deduction as the returned value from GetDeduction()
    printf("Deduction: $%d\n", deduction); // Print deduction

    int taxableIncome = CalcTaxable(AGI, deduction); // Declare and initialize taxableIncome as the returned value from CalcTaxable()
    printf("Taxable Income: $%d\n", taxableIncome); // Print taxable income

    int federalTax = CalcTax(status, taxableIncome); // Declare and initialize federalTax as the returned value from CalcTax()
    printf("Federal Tax: $%d\n", federalTax); // Print federal tax

    int taxStillDue = CalcTaxDue(federalTax, taxesWithheld); // Declare and initialize taxStillDue as the returned value from CalcTaxDue()
    CheckOwedOrRefund(taxStillDue); // Check for taxes owed or tax refund (function includes print statements)

    return 0; // Return end code

}