@page "/components/charts/scatter"

<PageTitle>Scatter Chart — Lumeo</PageTitle>

<PageHeader Title="Scatter Chart" Description="Reveal correlations and distributions between two continuous variables. Ideal for data exploration and identifying clusters or outliers." />

<Stack Gap="8">
    <ComponentDemo Title="Multi-Series Scatter" Description="Compare two cohorts across the same axes — experience vs. performance score — to spot separation between groups." Code="@_basicCode">
        <Container>
            <ScatterChart Series="_series" />
        </Container>
    </ComponentDemo>

    <ComponentDemo Title="Customer Segments" Description="Plot customer lifetime value against support ticket volume across three distinct customer segments." Code="@_segmentsCode">
        <Container>
            <ScatterChart Series="_segmentSeries" />
        </Container>
    </ComponentDemo>

    <ComponentDemo Title="Fixed Bubble Size" Description="Set a uniform BubbleSize to make individual data points stand out, useful when the x/y position carries all the information." Code="@_bubbleCode">
        <Container>
            <ScatterChart Series="_series" BubbleSize="14" />
        </Container>
    </ComponentDemo>

    <ComponentDemo Title="Single Series — No Legend" Description="A single-series view with the legend hidden keeps the chart minimal when context is provided by surrounding copy." Code="@_singleCode">
        <Container>
            <ScatterChart Series="_singleSeries" ShowLegend="false" />
        </Container>
    </ComponentDemo>

    <ComponentDemo Title="Custom Colors" Description="Override the default color palette to match brand or encode semantic meaning (e.g. green = on-track, red = at-risk)." Code="@_customColorsCode">
        <Container>
            <ScatterChart Series="_segmentSeries" Colors="_segmentColors" />
        </Container>
    </ComponentDemo>
    <ComponentDemo Title="Loading state" Description="Shape-aware skeleton with reserved space for legend and axes — no layout shift when real data arrives.">
        <Container>
            <Stack Gap="4">
                <Stack Direction="Stack.StackDirection.Horizontal" Gap="4" Align="center" Wrap="true">
                    <Button OnClick="SimulateLoadingAsync" Disabled="@_loading">Simulate loading</Button>
                    <Stack Direction="Stack.StackDirection.Horizontal" Gap="2" Align="center">
                        <Switch @bind-Value="_keepLoading" Id="keep-loading" />
                        <label for="keep-loading" class="text-sm text-muted-foreground cursor-pointer">Hold skeleton open</label>
                    </Stack>
                    <Stack Direction="Stack.StackDirection.Horizontal" Gap="2" Align="center">
                        <label class="text-sm text-muted-foreground">Duration: @(_simulateDurationMs / 1000.0)s</label>
                        <input type="range" min="500" max="10000" step="500" @bind-value="_simulateDurationMs" @bind-value:event="oninput" class="w-32 accent-primary" />
                    </Stack>
                    <Stack Direction="Stack.StackDirection.Horizontal" Gap="2" Align="center">
                        <label class="text-sm text-muted-foreground">Cycle: @_phantomCycleMs ms</label>
                        <input type="range" min="300" max="3000" step="100" @bind-value="_phantomCycleMs" @bind-value:event="oninput" class="w-32 accent-primary" />
                    </Stack>
                </Stack>
                <ScatterChart Series="_series" PhantomCycleMs="@_phantomCycleMs" IsLoading="@LoadingComputed" Height="320px" />
            </Stack>
        </Container>
    </ComponentDemo>
</Stack>

<!-- API Reference -->
<Stack Gap="6" Class="mt-12">
    <Heading Level="2">API Reference</Heading>
    <Stack Gap="8">
        <Stack>
            <Heading Level="3" Class="mb-3">ScatterChart</Heading>
            <Stack Class="rounded-lg border border-border/40 overflow-x-auto">
                <table class="w-full min-w-[600px] text-sm">
                    <thead>
                        <tr class="border-b border-border/40 bg-muted/40">
                            <th class="text-left p-3 font-medium text-foreground">Property</th>
                            <th class="text-left p-3 font-medium text-foreground">Type</th>
                            <th class="text-left p-3 font-medium text-foreground">Default</th>
                            <th class="text-left p-3 font-medium text-foreground">Description</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-border/40">
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Series</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">List&lt;ScatterSeriesData&gt;</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">[]</td>
                            <td class="p-3 text-muted-foreground">Data series with Name and Points (double[] coordinate pairs).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">BubbleSize</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">int?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Fixed symbol size in pixels.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ShowLegend</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">true</td>
                            <td class="p-3 text-muted-foreground">Shows legend when multiple series present.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Colors</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">List&lt;string&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Custom color palette for series.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ShowTooltip</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">true</td>
                            <td class="p-3 text-muted-foreground">Enables the hover tooltip.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">IsLoading</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">When true, renders a shape-matched loading skeleton in place of the chart. Bind to your async fetch state.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ShowLoadingSkeleton</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">true</td>
                            <td class="p-3 text-muted-foreground">Set to false to opt out of the skeleton (chart area stays empty while IsLoading is true).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">SkeletonKind</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">ChartSkeletonKind</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">(chart default)</td>
                            <td class="p-3 text-muted-foreground">Override the skeleton silhouette (Bars, Line, Area, Pie, Scatter, Grid, Generic).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">SkeletonStyle</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">ChartSkeletonStyle</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">Phantom</td>
                            <td class="p-3 text-muted-foreground">Phantom renders the real chart with placeholder data and morphs to real data via ECharts animation. Silhouette falls back to the legacy SVG skeleton overlay.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ShowLoadingLabel</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">true</td>
                            <td class="p-3 text-muted-foreground">Shows a small "Loading&hellip;" pill in the top-right corner whenever <code class="rounded bg-muted px-1 py-0.5 text-xs font-mono">IsLoading</code> is true. Layered on top of any <code class="rounded bg-muted px-1 py-0.5 text-xs font-mono">SkeletonStyle</code>. Set to false for bare visuals. <strong>(rc.18)</strong></td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">LoadingText</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">"Loading&hellip;"</td>
                            <td class="p-3 text-muted-foreground">Label rendered next to the spinner inside the loading pill. Set to empty to show the spinner alone. <strong>(rc.18)</strong></td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Width</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">"100%"</td>
                            <td class="p-3 text-muted-foreground">CSS width of the chart container.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Height</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">"350px"</td>
                            <td class="p-3 text-muted-foreground">CSS height of the chart container.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Theme</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Optional ECharts theme name override.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">PhantomCycleMs</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">int</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">1400</td>
                            <td class="p-3 text-muted-foreground">Phantom-mode refresh interval in milliseconds. Lower = faster data cycling while loading.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ShowDataLabels</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">When true, displays value labels on each scatter point.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">LabelPosition</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">"top"</td>
                            <td class="p-3 text-muted-foreground">Position of data labels relative to each point.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">LabelFormat</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Optional ECharts label formatter string for data labels.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">DataZoom</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">Enables the interactive data-zoom slider beneath the chart.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">Toolbox</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">false</td>
                            <td class="p-3 text-muted-foreground">Shows the ECharts toolbox with export and zoom controls.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">ColorPalette</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">List&lt;string&gt;?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Alternate full color palette applied to the chart.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">AnimationDuration</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">int?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Animation duration in milliseconds when data changes.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">AnimationEasing</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">string?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">ECharts easing function name for animation curves.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">MarkLine</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">EChartMarkLine?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Optional mark lines overlaid on the chart (e.g. averages, thresholds).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">MarkPoint</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">EChartMarkPoint?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Optional mark points highlighting min/max or custom values.</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">MarkArea</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">EChartMarkArea?</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">null</td>
                            <td class="p-3 text-muted-foreground">Optional shaded mark areas highlighting value bands.</td>
                        </tr>
                    </tbody>
                </table>
            </Stack>
        </Stack>
    </Stack>
</Stack>

@code {
    private List<ScatterChart.ScatterSeriesData> _series = new()
    {
        new()
        {
            Name = "Team Alpha",
            Points = new()
            {
                new[] { 14.0, 82.3 }, new[] { 22.0, 74.1 }, new[] { 8.0, 91.5 },
                new[] { 31.0, 65.8 }, new[] { 18.0, 78.4 }, new[] { 25.0, 69.2 },
                new[] { 11.0, 87.6 }
            }
        },
        new()
        {
            Name = "Team Beta",
            Points = new()
            {
                new[] { 28.0, 55.3 }, new[] { 37.0, 48.7 }, new[] { 19.0, 62.1 },
                new[] { 43.0, 41.5 }, new[] { 33.0, 51.8 }, new[] { 24.0, 58.9 },
                new[] { 40.0, 45.2 }
            }
        }
    };

    private List<ScatterChart.ScatterSeriesData> _segmentSeries = new()
    {
        new()
        {
            Name = "Enterprise",
            Points = new()
            {
                new[] { 2.1, 94200.0 }, new[] { 1.3, 128400.0 }, new[] { 3.4, 87600.0 },
                new[] { 0.8, 142800.0 }, new[] { 4.2, 76300.0 }, new[] { 1.9, 111200.0 },
                new[] { 2.7, 98700.0 }
            }
        },
        new()
        {
            Name = "Professional",
            Points = new()
            {
                new[] { 5.8, 34200.0 }, new[] { 7.2, 28700.0 }, new[] { 4.1, 41800.0 },
                new[] { 9.3, 22400.0 }, new[] { 6.4, 31600.0 }, new[] { 8.1, 26300.0 },
                new[] { 5.2, 38900.0 }
            }
        },
        new()
        {
            Name = "Starter",
            Points = new()
            {
                new[] { 11.4, 8200.0 }, new[] { 14.7, 6300.0 }, new[] { 8.9, 11400.0 },
                new[] { 18.2, 4800.0 }, new[] { 12.6, 7100.0 }, new[] { 16.3, 5600.0 },
                new[] { 10.1, 9800.0 }
            }
        }
    };

    private List<ScatterChart.ScatterSeriesData> _singleSeries = new()
    {
        new()
        {
            Name = "Conversion Rate vs Ad Spend",
            Points = new()
            {
                new[] { 1200.0, 3.4 }, new[] { 2400.0, 4.1 }, new[] { 3600.0, 4.8 },
                new[] { 4800.0, 5.2 }, new[] { 6000.0, 5.9 }, new[] { 7200.0, 6.1 },
                new[] { 8400.0, 6.4 }, new[] { 9600.0, 6.8 }, new[] { 10800.0, 7.1 },
                new[] { 12000.0, 7.3 }
            }
        }
    };

    private List<string> _segmentColors = new() { "#6366f1", "#f59e0b", "#10b981" };

    private string _basicCode = @"<ScatterChart Series=""_series"" />";
    private string _segmentsCode = @"<ScatterChart Series=""_segmentSeries"" />";
    private string _bubbleCode = @"<ScatterChart Series=""_series"" BubbleSize=""14"" />";
    private string _singleCode = @"<ScatterChart Series=""_singleSeries"" ShowLegend=""false"" />";
    private string _customColorsCode = @"<ScatterChart Series=""_segmentSeries"" Colors=""_segmentColors"" />";

    private bool _loading;
    private bool _keepLoading;
    private bool LoadingComputed => _loading || _keepLoading;
    private int _simulateDurationMs = 2000;
    private int _phantomCycleMs = 1400;

    private async Task SimulateLoadingAsync()
    {
        _loading = true;
        await Task.Delay(_simulateDurationMs);
        _loading = false;
    }
}
