To solve this optimization problem, we need to define the decision variables and the objective function. Let's denote the number of first-class tickets as `x` and the number of economy-class tickets as `y`.

The profit made on each first-class ticket is $150, and on each economy-class ticket is $350. The objective is to maximize the total profit, which can be represented by the equation: 

Maximize: 150x + 350y

We have two main constraints:
1. The total number of tickets sold cannot exceed 150.
2. At least 20 tickets must be reserved for first-class.
3. At least 3 times as many people prefer to travel by economy-class than by first-class.

Mathematically, these constraints can be represented as follows:
- x + y ≤ 150 (Total tickets constraint)
- x ≥ 20 (Minimum first-class tickets constraint)
- y ≥ 3x (Economy-class preference constraint)

Now, let's express this problem in Gurobi code:

```python
from gurobipy import *

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

# Define the decision variables
x = m.addVar(name="first_class_tickets", vtype=GRB.INTEGER, lb=0)
y = m.addVar(name="economy_class_tickets", vtype=GRB.INTEGER, lb=0)

# Set the objective function: Maximize profit
m.setObjective(150*x + 350*y, GRB.MAXIMIZE)

# Add constraints
m.addConstr(x + y <= 150, name="total_tickets_constraint")
m.addConstr(x >= 20, name="minimum_first_class_constraint")
m.addConstr(y >= 3*x, name="economy_class_preference_constraint")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"First-class tickets: {x.x}")
    print(f"Economy-class tickets: {y.x}")
    print(f"Total profit: ${150*x.x + 350*y.x}")
else:
    print("No optimal solution found")
```