from itertools import product


def spiral_XYs(min_X, max_X, min_Y, max_Y):
    """
    >>> spiral_XYs(1, 3, 1, 3)
    [(2, 2), (2, 3), (1, 3), (1, 2), (1, 1), (2, 1), (3, 1), (3, 2), (3, 3)]

    >>> spiral_XYs(1, 2, 1, 2)
    [(1, 2), (1, 1), (2, 1), (2, 2)]

    >>> spiral_XYs(1, 1, 1, 1)
    [(1, 1)]

    >>> spiral_XYs(1, 4, 1, 1)
    [(1, 1), (2, 1), (3, 1), (4, 1)]

    >>> spiral_XYs(1, 1, 1, 3)
    [(1, 1), (1, 2), (1, 3)]

    """
    if (min_X > max_X) or (min_Y > max_Y):
        raise ValueError
    XYs = list(product(range(min_X, max_X + 1), range(min_Y, max_Y + 1)))
    res_reverse = []
    while XYs:
        # Go down right side
        app = [(X, Y) for X, Y in XYs if X == max_X and min_Y <= Y <= max_Y]
        XYs = [(X, Y) for X, Y in XYs if not (X, Y) in app]
        app = sorted(app, key=lambda x: x[1], reverse=True)
        res_reverse += app
        max_X -= 1

        # Go left lower side
        app = [(X, Y) for X, Y in XYs if Y == min_Y and min_X <= X <= max_X]
        XYs = [(X, Y) for X, Y in XYs if not (X, Y) in app]
        app = sorted(app, key=lambda x: x[0], reverse=True)
        res_reverse += app
        min_Y += 1

        # Go up left side
        app = [(X, Y) for X, Y in XYs if X == min_X and min_Y <= Y <= max_Y]
        XYs = [(X, Y) for X, Y in XYs if not (X, Y) in app]
        app = sorted(app, key=lambda x: x[1])
        res_reverse += app
        min_X += 1

        # Go right upper side
        app = [(X, Y) for X, Y in XYs if Y == max_Y and min_X <= X <= max_X]
        XYs = [(X, Y) for X, Y in XYs if not (X, Y) in app]
        app = sorted(app, key=lambda x: x[0])
        res_reverse += app
        max_Y -= 1

    res = list(reversed(res_reverse))
    return res