import marimo

__generated_with = "0.15.1"
app = marimo.App(width="columns")


@app.cell(column=0)
def _():
    import marimo as mo
    from vega_datasets import data
    import altair as alt
    import pandas as pd
    import pyarrow
    return alt, data, mo, pd


@app.cell
def _(mo):
    mo.md(r"""Visualizacion de barras categóricas Pudiendo seleccionar una""")
    return


@app.cell
def _(alt, mo, pd):

    dataset = pd.DataFrame([
        {"a": "A", "b": 28},
        {"a": "B", "b": 55},
        {"a": "C", "b": 43},
        {"a": "D", "b": 91},
        {"a": "E", "b": 81},
        {"a": "F", "b": 53},
        {"a": "G", "b": 19},
        {"a": "H", "b": 87},
        {"a": "I", "b": 52},
    ])


    _x = "a:O" # categórica
    _y = "b:Q" # numérica

    # Selección solo por clic
    select1 = alt.selection_point(name="select", on="click")

    stroke_width1 = (
        alt.when(select1).then(alt.value(2, empty=False)).otherwise(alt.value(0))
    )

    _bar_chart1 = (
        alt.Chart(
            dataset,
            height=200,
            config=alt.Config(scale=alt.ScaleConfig(bandPaddingInner=0.2)),
        )
        .mark_bar(fill="#4C78A8", stroke="black", cursor="pointer")
        .encode(
            x= _x,  
            y= _y, 
            fillOpacity=alt.when(select1).then(alt.value(1)).otherwise(alt.value(0.3)),
            strokeWidth=stroke_width1,
        )
        .add_params(select1)
    )

    bar_chart1 = mo.ui.altair_chart(_bar_chart1)
    bar_chart1

    return bar_chart1, dataset


@app.cell
def _(bar_chart1, dataset, mo):
    filtered_data1 = mo.ui.table(bar_chart1.value if len(bar_chart1.value) else dataset)
    filtered_data1
    return


@app.cell
def _(mo):
    mo.md(r"""Visualización de barras categóricas con media pudiéndose seleccionar varias""")
    return


@app.cell
def _(alt, data, mo):

    dataset_weather = data.seattle_weather()

    # Crear columnas explícitas de mes para evitar errores en marimo
    dataset_weather2 = dataset_weather.copy()
    dataset_weather2["month_date"] = dataset_weather2["date"].dt.month
    dataset_weather2["month_name"] = dataset_weather2["date"].dt.strftime("%b")  # Ej: Jan, Feb...

    # Variables X y Y
    _x = "month_name:O"        # categórica
    _y = "mean(precipitation):Q"  # numérica

    # Selección por intervalo (brush) en el eje X
    brush2 = alt.selection_interval(encodings=["x"])

    bars2 = (
        alt.Chart(dataset_weather2)
        .mark_bar()
        .encode(
            x=_x,
            y=_y,
            opacity=alt.when(brush2).then(alt.value(1)).otherwise(alt.value(0.7)),
        )
        .add_params(brush2)
    )

    line2 = (
        alt.Chart(dataset_weather2)
        .mark_rule(color="firebrick")
        .encode(
            y=_y,
            size=alt.SizeValue(3),
        )
        .transform_filter(brush2)
    )

    layered_chart2 = alt.layer(bars2, line2)

    weather_chart2 = mo.ui.altair_chart(layered_chart2)
    weather_chart2

    return dataset_weather2, weather_chart2


@app.cell
def _(dataset_weather2, mo, weather_chart2):
    filtered_weather2 = mo.ui.table(weather_chart2.value if len(weather_chart2.value) else dataset_weather2)
    filtered_weather2
    return


@app.cell(column=1)
def _(mo):
    mo.md(r"""Gráfico con agrupación en Slider""")
    return


@app.cell
def _(alt, data, mo):
    # from vega_datasets import data

    # Cargar dataset
    dataset_movies3 = data.movies()

    # Variables X e Y
    _x = "IMDB_Rating:Q"             # numérica
    _y = "Rotten_Tomatoes_Rating:Q"  # numérica

    # Slider de Altair (param embebido en el gráfico)
    slider_binding3 = alt.binding_range(min=0, max=10, step=0.1)
    threshold3 = alt.param(name="threshold3", value=5, bind=slider_binding3)

    # Capa 1: puntos con IMDB >= threshold
    points3 = (
        alt.Chart(dataset_movies3)
        .mark_circle()
        .encode(
            x=alt.X(_x, title="IMDB Rating"),
            y=alt.Y(_y, title="Rotten Tomatoes Rating")
        )
        .transform_filter(
            alt.datum.IMDB_Rating >= threshold3
        )
    )

    # Capa 2: puntos agregados con IMDB < threshold
    binned3 = (
        alt.Chart(dataset_movies3)
        .mark_circle()
        .encode(
            x=alt.X(_x, bin=alt.Bin(maxbins=10)),
            y=alt.Y(_y, bin=alt.Bin(maxbins=10)),
            size=alt.Size("count():Q", scale=alt.Scale(domain=[0,160]))
        )
        .transform_filter(
            alt.datum.IMDB_Rating < threshold3
        )
    )

    # Capa 3: regla vertical del threshold
    rule3 = (
        alt.Chart()
        .mark_rule(color="gray")
        .encode(
            strokeWidth=alt.StrokeWidth(value=6),
            x=alt.X(datum=alt.expr(threshold3.name), type="quantitative")
        )
    )

    # Combinar capas
    layered_movies3 = alt.layer(points3, binned3, rule3).add_params(threshold3)

    movies_chart3 = mo.ui.altair_chart(layered_movies3)
    movies_chart3

    return


@app.cell
def _(mo):
    mo.md(r"""Altair está trabajando bien en marimor pero aún tiene algunas partes por pulir como por ejemplo la capacidad de tener dos gráficos  En una misma celda También tiene problemas a la hora de tener Y filtrar En diferentes celdas además de pasar datos como por ejemplo el Slider""")
    return


@app.cell
def _(alt, data, mo):
    # Dataset
    dataset_movies4 = data.movies()

    # Variables
    x1 = "IMDB_Rating:Q"             # numérica
    y1 = "Rotten_Tomatoes_Rating:Q"  # numérica

    # Selección
    pts4 = alt.selection_point(encodings=['x'], name="pts4")

    # Heatmap base
    rect4 = (
        alt.Chart(dataset_movies4)
        .mark_rect()
        .encode(
            x=alt.X(x1, bin=True),
            y=alt.Y(y1, bin=True),
            color=alt.Color(
                "count()",
                scale=alt.Scale(scheme="greenblue"),
                legend=alt.Legend(title="Total Records")
            )
        )
        .properties(width=550, height=300)
    )

    movies_rect4 = mo.ui.altair_chart(rect4.add_params(pts4))
    movies_rect4

    return dataset_movies4, pts4, x1, y1


@app.cell
def _(alt, dataset_movies4, mo, pts4, x1, y1):
    circ4 = (
        alt.Chart(dataset_movies4)
        .mark_point(color="grey")
        .encode(
            x=alt.X(x1, bin=True),
            y=alt.Y(y1, bin=True),
            size=alt.Size("count()", legend=alt.Legend(title="Records in Selection"))
        )
        .transform_filter(pts4)
        .properties(width=550, height=300)
    )

    movies_circ4 = mo.ui.altair_chart(circ4)
    movies_circ4

    return


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