import re
from collections import namedtuple
from typing import List

Ready4Display = namedtuple('Ready4Display', 'top bottom sep solution')


class WrongOperator(Exception):
    ...


class TooMuchDigits(Exception):
    ...


class OnlyDigitsAllowed(Exception):
    ...


def arrange_one(problem: str) -> Ready4Display:
    try:
        matches = re.match(r'\s*(?P<first>\d+)\s*(?P<op>.)\s*(?P<second>\d+)\s*$', problem).groupdict()
    except AttributeError:  # No match
        raise OnlyDigitsAllowed

    if matches['op'] not in ['+', '-']:
        raise WrongOperator

    max_len = max(len(x) for x in matches.values())
    if max_len > 4:
        raise TooMuchDigits

    return Ready4Display(
        matches['first'].rjust(max_len + 2, ' '),
        matches['op'] + ' ' + matches['second'].rjust(max_len, ' '),
        '-' * (max_len + 2),
        str(eval(problem)).rjust(max_len + 2, ' ')  # Unsafe!
    )


def arithmetic_arranger(problems: List[str], solve_it: bool = False) -> str:
    if len(problems) > 5:
        return 'Error: Too many problems.'

    try:
        solutions = [
            arrange_one(problem)
            for problem in problems
        ]
    except OnlyDigitsAllowed:
        return 'Error: Numbers must only contain digits.'
    except WrongOperator:
        return "Error: Operator must be '+' or '-'."
    except TooMuchDigits:
        return 'Error: Numbers cannot be more than four digits.'

    final_display = ''
    final_display += '    '.join(x.top for x in solutions) + '\n'
    final_display += '    '.join(x.bottom for x in solutions) + '\n'
    final_display += '    '.join(x.sep for x in solutions) + '\n'

    if solve_it:
        final_display += '    '.join(x.solution for x in solutions) + '\n'

    return final_display.rstrip()
