import plotly.express as px
from dash import Dash, dcc, html, Input, Output

df = px.data.gapminder().query("year == 2007")
continents = sorted(df.continent.unique())

app = Dash(__name__)
app.layout = html.Div(style={"fontFamily": "sans-serif", "padding": "16px"}, children=[
    html.H2("Life expectancy vs. income, 2007"),
    html.Div(style={"display": "flex", "gap": "16px"}, children=[
        html.Div(style={"width": "18%"}, children=[
            html.H4("Continent"),
            dcc.Checklist(id="cont", options=continents, value=continents,
                          labelStyle={"display": "block"}),
        ]),
        dcc.Graph(id="scatter", style={"width": "46%", "height": "520px"}),
        dcc.Graph(id="box", style={"width": "36%", "height": "520px"}),
    ]),
])

@app.callback(Output("scatter", "figure"), Input("cont", "value"))
def scatter(selected):
    d = df[df.continent.isin(selected)]
    return px.scatter(d, x="gdpPercap", y="lifeExp", color="continent", size="pop",
                      hover_name="country", log_x=True, size_max=40,
                      category_orders={"continent": continents})

@app.callback(Output("box", "figure"), Input("cont", "value"), Input("scatter", "selectedData"))
def box(selected, sel):
    d = df[df.continent.isin(selected)]
    if sel and sel.get("points"):
        d = d[d.country.isin([p["hovertext"] for p in sel["points"]])]
    return px.box(d, x="continent", y="lifeExp", color="continent", points="all",
                  category_orders={"continent": continents})

if __name__ == "__main__":
    app.run(port=8898)
