#!/usr/bin/env python
"""03 -- pandas DataFrame in, matplotlib figure out.

Both gradio majors in this bundle render gr.Plot from a matplotlib Figure.
Note MPLBACKEND=Agg (set by gradio-offline.env): a server with no display
cannot use an interactive backend.
"""
import matplotlib
matplotlib.use("Agg")           # must precede pyplot on a headless host
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import gradio as gr
from _common import launch


def sample_frame(rows=24, seed=0):
    rng = np.random.default_rng(seed)
    idx = pd.date_range("2026-01-01", periods=rows, freq="h")
    return pd.DataFrame({
        "timestamp": idx.strftime("%Y-%m-%d %H:%M"),
        "requests": rng.integers(80, 400, rows),
        "latency_ms": np.round(rng.normal(35, 9, rows), 1),
    })


def plot_frame(df: pd.DataFrame):
    if df is None or len(df) == 0:
        return None
    df = pd.DataFrame(df).copy()
    for col in ("requests", "latency_ms"):
        df[col] = pd.to_numeric(df[col], errors="coerce")

    fig, ax1 = plt.subplots(figsize=(8, 3.6), layout="constrained")
    ax1.bar(range(len(df)), df["requests"], color="#6aa8d8", label="requests")
    ax1.set_ylabel("requests")
    ax1.set_xlabel("sample")
    ax2 = ax1.twinx()
    ax2.plot(range(len(df)), df["latency_ms"], color="#d1603d",
             marker="o", ms=3, label="latency (ms)")
    ax2.set_ylabel("latency (ms)")
    ax1.set_title("Requests and latency")
    fig.legend(loc="outside upper right", fontsize=8)
    return fig


with gr.Blocks(title="DataFrame and plot") as demo:
    gr.Markdown("## Editable table, rendered as a chart\n"
                "Edit a cell, then press **Plot**.")
    table = gr.DataFrame(value=sample_frame(), label="Data", interactive=True)
    with gr.Row():
        regen = gr.Button("New random data")
        draw = gr.Button("Plot", variant="primary")
    chart = gr.Plot(label="Chart")

    regen.click(lambda: sample_frame(seed=np.random.randint(1e6)), None, table)
    draw.click(plot_frame, table, chart, api_name="plot")
    demo.load(plot_frame, table, chart)

if __name__ == "__main__":
    launch(demo)
