To solve this optimization problem, we need to define the decision variables, objective function, and constraints. Let's denote the number of chairs as $C$ and the number of shelves as $S$. The profit per chair is $50, and the profit per shelf is $55.

The objective function is to maximize the total profit:
\[ \text{Maximize} \quad 50C + 55S \]

Now, let's define the constraints based on the available time for assembly and painting. Each chair requires 30 minutes of assembly, so $C$ chairs require $30C$ minutes. Similarly, each shelf requires 20 minutes of assembly, so $S$ shelves require $20S$ minutes. The total assembly time should not exceed 3000 minutes:
\[ 30C + 20S \leq 3000 \]

For painting, each chair requires 50 minutes, and each shelf requires 60 minutes. Thus, the total painting time for $C$ chairs and $S$ shelves should not exceed 4000 minutes:
\[ 50C + 60S \leq 4000 \]

Additionally, we cannot produce a negative number of chairs or shelves, so both $C$ and $S$ must be non-negative:
\[ C \geq 0, S \geq 0 \]

Given these constraints and the objective function, we can now write the Gurobi code in Python to solve this linear programming problem:

```python
from gurobipy import *

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

# Define the decision variables
C = m.addVar(lb=0, vtype=GRB.CONTINUOUS, name="Chairs")
S = m.addVar(lb=0, vtype=GRB.CONTINUOUS, name="Shelves")

# Set the objective function: Maximize profit
m.setObjective(50*C + 55*S, GRB.MAXIMIZE)

# Add constraints
m.addConstr(30*C + 20*S <= 3000, "Assembly_Time")
m.addConstr(50*C + 60*S <= 4000, "Painting_Time")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print(f"Optimal solution: Produce {C.x} chairs and {S.x} shelves.")
    print(f"Maximum profit: ${50*C.x + 55*S.x}")
else:
    print("No optimal solution found")
```