"""Program that generates a synthetic test data file with U.S. expenditure records."""

from random import randint, choice

LINES_TO_GENERATE = 10000
EXPENSE_CATEGORIES = ['Rent',
                      'Utilities',
                      'Office Supplies',
                      'Fuel',
                      'Meals & Entertainment',
                      'Salaries, Bonuses, and Benefits',
                      'Vehicle Lease'
                      ]
STARTING_ISO_DATE = '2023-01-01'
ENDING_ISO_DATE = '2024-12-31'
LOWEST_AMOUNT = 100.00
HIGHEST_AMOUNT = 2000.00
OUTFILE_NAME = 'data/us_expense_records.csv'


def main():
    with open(OUTFILE_NAME, 'w', encoding='utf-8') as outfile:
        print('Date,Expense Category,Amount', file=outfile)

        for i in range(LINES_TO_GENERATE):
            date = get_random_date(STARTING_ISO_DATE, ENDING_ISO_DATE)
            category = get_random_expense_category(EXPENSE_CATEGORIES)
            amount = get_random_dollar_amount(LOWEST_AMOUNT, HIGHEST_AMOUNT)
            content = f'{date},"{category}",{amount:.2f}'
            print(content, file=outfile)

        print(f'\n{LINES_TO_GENERATE:,} expense records have been written to {OUTFILE_NAME}')


def get_random_date(starting_iso_date, ending_iso_date):
    start_year, start_month, start_day = parse_iso_date(starting_iso_date)
    end_year, end_month, end_day = parse_iso_date(ending_iso_date)
    if start_year == end_year:
        random_year = start_year
    else:
        random_year = randint(start_year, end_year)
    random_month = randint(start_month, end_month)
    random_day = randint(1, determine_days_in_month(random_year, random_month))
    random_us_date = f'{random_month:02d}/{random_day:02d}/{random_year:4}'
    return random_us_date


def determine_days_in_month(the_year, the_month):
    if is_leap_year(the_year):
        february_days = 29
    else:
        february_days = 28
    if the_month in [4, 6, 9, 11]:
        max_days = 30
    elif the_month == 2:
        max_days = february_days
    else:
        max_days = 31
    return max_days


def is_leap_year(year):
    answer = False
    if (year % 4) == 0:
        if (year % 100) == 0:
            if (year % 400) == 0:
                answer = True
            else:
                answer = False
        else:
            answer = True
    else:
        answer = False
    return answer


def parse_iso_date(iso_date):
    year_as_string, month_as_string, day_as_string = iso_date.split('-')
    year = int(year_as_string)
    month = int(month_as_string)
    day = int(day_as_string)
    return year, month, day


def get_random_dollar_amount(lowest_amount, highest_amount):
    lowest_pennies = round(lowest_amount * 100)
    highest_pennies = round(highest_amount * 100)
    random_pennies = randint(lowest_pennies, highest_pennies)
    dollar_amount = random_pennies / 100.00
    rounded_dollar_amount = round(dollar_amount, 2)
    return rounded_dollar_amount


def get_random_expense_category(category_list):
    return choice(category_list)


main()
