import json


def write_grading_outputs(
    testcases: list,
    testcase_outputs: list,
    results_json: str,
    grade_txt: str
) -> str:
    """Write the grading output data to the specified paths."""

    ###########################################################################
    #
    # NOTE: Editing this file? Make sure that this function stays in-sync with
    #       grading/main_validator.cpp::validateTestCase()
    #
    ###########################################################################

    results = {'testcases': testcase_outputs}
    with open(results_json, 'w') as fd:
        json.dump(results, fd, indent=4)

    max_auto_points = sum(tc['points'] for tc in testcases)
    max_nonhidden_auto_points = sum(
        tc['points'] for tc in testcases if not tc.get('hidden', False)
    )

    auto_points = sum(r['points_awarded'] for r in testcase_outputs)
    nonhidden_auto_points = sum(
        r['points_awarded']
        for r, tc in zip(testcase_outputs, testcases)
        if not tc.get('hidden', False)
    )

    with open(grade_txt, 'w') as fd:
        # Write each test case's individual output
        for i, tc in enumerate(testcases):
            title = tc['title']
            extra_credit = tc.get('extra_credit', False)
            max_points = tc['points']
            points = testcase_outputs[i]['points_awarded']
            fd.write(f"Testcase {i:3}: {title:<50} ")

            if extra_credit:
                if points > 0:
                    fd.write(f"+{points:2} points")
                else:
                    fd.write(' ' * 10)
            elif max_points < 0:
                if points < 0:
                    fd.write(f"{points:3} points")
                else:
                    fd.write(' ' * 10)
            else:
                fd.write(f"{points:3} / {max_points:3}  ")

            if tc.get('hidden', False):
                fd.write("  [ HIDDEN ]")
            fd.write('\n')

        # Write the final lines
        autograde_total_msg = (
            f"{'Automatic grading total:':<64}{auto_points:3} /"
            f"{max_auto_points:3}\n"
        )
        fd.write(autograde_total_msg)
        fd.write(f"{'Non-hidden automatic grading total:':<64}{nonhidden_auto_points:3} /"
                 f"{max_nonhidden_auto_points:3}\n")
    return autograde_total_msg