To solve the given optimization problem, we first need to convert the natural language description into a symbolic representation. Let's denote the number of peanut butter sandwiches as $x_1$ and the number of chocolate spread sandwiches as $x_2$. The objective is to maximize profit, which can be represented by the objective function $3x_1 + 2x_2$, given the profits per sandwich.

The constraints based on the problem description are:
- The store can make at most 150 sandwiches: $x_1 + x_2 \leq 150$
- They must sell at least 45 peanut butter sandwiches: $x_1 \geq 45$
- They must sell at least 65 chocolate spread sandwiches: $x_2 \geq 65$
- They can make at most 80 peanut butter sandwiches due to the spread limit: $x_1 \leq 80$
- They can make at most 100 chocolate spread sandwiches due to the spread limit: $x_2 \leq 100$

Therefore, the symbolic representation of the problem is:
```json
{
    'sym_variables': [('x1', 'peanut butter sandwiches'), ('x2', 'chocolate spread sandwiches')],
    'objective_function': '3*x1 + 2*x2',
    'constraints': [
        'x1 + x2 <= 150',
        'x1 >= 45',
        'x2 >= 65',
        'x1 <= 80',
        'x2 <= 100'
    ]
}
```

Given this symbolic representation, we can now write the Gurobi code to solve the optimization problem. The reasoning behind the code is straightforward: it sets up a linear programming model with two variables (`x1` and `x2`), defines the objective function to maximize profit, and adds constraints as specified by the problem description.

```python
from gurobipy import *

# Create a new model
m = Model("Sandwich_Problem")

# Create variables
x1 = m.addVar(lb=45, ub=80, name="peanut_butter_sandwiches")
x2 = m.addVar(lb=65, ub=100, name="chocolate_spread_sandwiches")

# Set the objective function to maximize profit
m.setObjective(3*x1 + 2*x2, GRB.MAXIMIZE)

# Add constraint: total sandwiches cannot exceed 150
m.addConstr(x1 + x2 <= 150, name="total_sandwiches_limit")

# Optimize model
m.optimize()

# Print solution
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Peanut butter sandwiches: {x1.x}")
    print(f"Chocolate spread sandwiches: {x2.x}")
    print(f"Maximum profit: {m.objVal}")
else:
    print("No optimal solution found")
```