@page "/docs/services/theme"
@namespace Lumeo.Docs.Pages.Docs.Services

@implements IDisposable
@using Lumeo.Services
@inject ThemeService ThemeService

<PageTitle>Theme Service — Lumeo</PageTitle>

<PageHeader Title="Theme Service" Description="Switch between light, dark, and system mode, change color schemes at runtime, and react to theme changes." />

<Stack Gap="10">

    <!-- Current State (Live) -->
    <Stack>
        <Stack Gap="4">
            <Heading Level="2">Current State</Heading>
            <Lumeo.Text Size="sm" Color="muted" Leading="relaxed">
                These values update in real time as you interact with the demos below. This is the live state of the
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ThemeService</code> singleton.
            </Lumeo.Text>

            <Grid Class="grid-cols-1 sm:grid-cols-3 gap-4">
                <Card Class="p-4">
                    <Stack Gap="2">
                        <Lumeo.Text Size="xs" Color="muted" Weight="medium">CurrentMode</Lumeo.Text>
                        <Flex Gap="2" Align="center">
                            <Blazicon Svg="@(ThemeService.CurrentMode == ThemeMode.Dark ? Lucide.Moon : ThemeService.CurrentMode == ThemeMode.Light ? Lucide.Sun : Lucide.Monitor)" class="h-5 w-5 text-primary" />
                            <Lumeo.Text Size="lg" Weight="semibold">@ThemeService.CurrentMode</Lumeo.Text>
                        </Flex>
                    </Stack>
                </Card>
                <Card Class="p-4">
                    <Stack Gap="2">
                        <Lumeo.Text Size="xs" Color="muted" Weight="medium">CurrentScheme</Lumeo.Text>
                        <Flex Gap="2" Align="center">
                            @{ var schemeInfo = ThemeService.AvailableSchemes.FirstOrDefault(s => s.Id == ThemeService.CurrentScheme); }
                            @if (schemeInfo != null)
                            {
                                <Lumeo.Text As="span" Class="inline-block h-4 w-4 rounded-full ring-1 ring-border" style="@($"background: {schemeInfo.PreviewColor}")"></Lumeo.Text>
                            }
                            <Lumeo.Text Size="lg" Weight="semibold" Class="capitalize">@ThemeService.CurrentScheme</Lumeo.Text>
                        </Flex>
                    </Stack>
                </Card>
                <Card Class="p-4">
                    <Stack Gap="2">
                        <Lumeo.Text Size="xs" Color="muted" Weight="medium">IsDark</Lumeo.Text>
                        <Flex Gap="2" Align="center">
                            <Badge Variant="@(ThemeService.IsDark ? Badge.BadgeVariant.Default : Badge.BadgeVariant.Outline)">
                                @(ThemeService.IsDark ? "true" : "false")
                            </Badge>
                        </Flex>
                    </Stack>
                </Card>
            </Grid>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Quick Start -->
    <Stack>
        <Stack Gap="4">
            <Heading Level="2">Quick Start</Heading>
            <Lumeo.Text Size="sm" Color="muted" Leading="relaxed">
                Inject <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ThemeService</code> and call
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">InitializeAsync()</code> once on first render.
                This reads the user's persisted preference from <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">localStorage</code>
                and applies it to the page.
            </Lumeo.Text>

            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">@@inject ThemeService ThemeService

@@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await ThemeService.InitializeAsync();
            StateHasChanged();
        }
    }
}</Stack>

            <Alert Variant="Alert.AlertVariant.Info">
                <Lumeo.Text Size="sm">
                    <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">InitializeAsync</code> requires JS interop, so it must be called in
                    <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">OnAfterRenderAsync</code>, not
                    <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">OnInitialized</code>.
                </Lumeo.Text>
            </Alert>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Dark Mode (Live Demos) -->
    <Stack>
        <Stack Gap="6">
            <Stack Gap="2">
                <Heading Level="2">Dark Mode</Heading>
                <Lumeo.Text Size="sm" Color="muted" Leading="relaxed">
                    Toggle between light and dark mode, or let the operating system decide. Click the buttons below to see the page theme change instantly.
                </Lumeo.Text>
            </Stack>

            <!-- Toggle Demo -->
            <Stack Gap="3">
                <Heading Level="3">Toggle</Heading>
                <Lumeo.Text Size="sm" Color="muted">
                    Switches between light and dark mode. The simplest way to add a theme toggle to your app.
                </Lumeo.Text>
                <Flex Gap="3" Align="center">
                    <Button Variant="Button.ButtonVariant.Outline" OnClick="HandleToggle">
                        <Blazicon Svg="@(ThemeService.IsDark ? Lucide.Sun : Lucide.Moon)" class="h-4 w-4 mr-2" />
                        @(ThemeService.IsDark ? "Switch to Light" : "Switch to Dark")
                    </Button>
                    <Badge Variant="Badge.BadgeVariant.Secondary">
                        IsDark = @(ThemeService.IsDark ? "true" : "false")
                    </Badge>
                </Flex>
                <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">await ThemeService.ToggleModeAsync();</Stack>
            </Stack>

            <!-- Explicit Mode Demo -->
            <Stack Gap="3">
                <Heading Level="3">Set Explicit Mode</Heading>
                <Lumeo.Text Size="sm" Color="muted">
                    Set a specific mode directly. The active mode is highlighted.
                </Lumeo.Text>
                <Flex Gap="2" Align="center" Wrap="true">
                    @foreach (var mode in new[] { ThemeMode.Light, ThemeMode.Dark, ThemeMode.System })
                    {
                        var icon = mode switch
                        {
                            ThemeMode.Light => Lucide.Sun,
                            ThemeMode.Dark => Lucide.Moon,
                            _ => Lucide.Monitor,
                        };
                        var isActive = ThemeService.CurrentMode == mode;
                        var capturedMode = mode;
                        <Button Variant="@(isActive ? Button.ButtonVariant.Default : Button.ButtonVariant.Outline)"
                                OnClick="@(async () => await ThemeService.SetModeAsync(capturedMode))">
                            <Blazicon Svg="@icon" class="h-4 w-4 mr-2" />
                            @mode
                        </Button>
                    }
                </Flex>
                <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">// Set to a specific mode
await ThemeService.SetModeAsync(ThemeMode.Light);
await ThemeService.SetModeAsync(ThemeMode.Dark);
await ThemeService.SetModeAsync(ThemeMode.System);</Stack>
            </Stack>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Color Schemes (Live Demos) -->
    <Stack>
        <Stack Gap="6">
            <Stack Gap="2">
                <Heading Level="2">Color Schemes</Heading>
                <Lumeo.Text Size="sm" Color="muted" Leading="relaxed">
                    Change the entire color palette at runtime. Click a scheme below to apply it to this page.
                    The active scheme is indicated by a ring.
                </Lumeo.Text>
            </Stack>

            <Stack Class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
                @foreach (var scheme in ThemeService.AvailableSchemes)
                {
                    var isActive = ThemeService.CurrentScheme == scheme.Id;
                    var capturedSchemeId = scheme.Id;
                    <button class="@($"flex items-center gap-3 rounded-lg border p-4 text-left transition-all hover:bg-accent/50 {(isActive ? "border-primary ring-1 ring-primary bg-accent/30" : "border-border")}")"
                            @onclick="@(async () => await ThemeService.SetSchemeAsync(capturedSchemeId))">
                        <Lumeo.Text As="span" Class="inline-block h-6 w-6 rounded-full ring-1 ring-border shrink-0" style="@($"background: {scheme.PreviewColor}")"></Lumeo.Text>
                        <Stack Gap="0">
                            <Lumeo.Text Size="sm" Weight="medium">@scheme.DisplayName</Lumeo.Text>
                            <Lumeo.Text Size="xs" Color="muted" Class="font-mono">@scheme.Id</Lumeo.Text>
                        </Stack>
                        @if (isActive)
                        {
                            <Blazicon Svg="Lucide.Check" class="h-4 w-4 text-primary ml-auto" />
                        }
                    </button>
                }
            </Stack>

            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">// Change the active color scheme
await ThemeService.SetSchemeAsync("blue");

// Read the current scheme
string current = ThemeService.CurrentScheme; // e.g. "zinc"

// Iterate all available schemes
foreach (var scheme in ThemeService.AvailableSchemes)
{
    // scheme.Id           => "zinc"
    // scheme.DisplayName  => "Orange"
    // scheme.PreviewColor => "hsl(14 70% 50%)"
}</Stack>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Listening for Changes -->
    <Stack>
        <Stack Gap="4">
            <Heading Level="2">Listening for Changes</Heading>
            <Lumeo.Text Size="sm" Color="muted" Leading="relaxed">
                Subscribe to the <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">OnThemeChanged</code> event
                to update your component whenever the user switches themes. Always unsubscribe in
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">Dispose()</code> to prevent memory leaks.
            </Lumeo.Text>

            <Stack Class="code-block rounded-lg border border-border/40 bg-muted px-4 py-3 font-mono text-sm text-foreground whitespace-pre">@@implements IDisposable
@@inject ThemeService ThemeService

&lt;p&gt;Current mode: @@ThemeService.CurrentMode&lt;/p&gt;
&lt;p&gt;Current scheme: @@ThemeService.CurrentScheme&lt;/p&gt;
&lt;p&gt;Is dark: @@ThemeService.IsDark&lt;/p&gt;

@@code {
    protected override void OnInitialized()
    {
        ThemeService.OnThemeChanged += HandleThemeChanged;
    }

    private void HandleThemeChanged()
    {
        // Properties are already updated when this fires
        _ = InvokeAsync(StateHasChanged);
    }

    public void Dispose()
    {
        ThemeService.OnThemeChanged -= HandleThemeChanged;
    }
}</Stack>

            <Alert Variant="Alert.AlertVariant.Warning">
                <Lumeo.Text Size="sm">
                    Always use <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">await InvokeAsync(StateHasChanged)</code>
                    inside the handler. The event may fire from a non-UI context, and calling
                    <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">StateHasChanged()</code> directly can throw.
                </Lumeo.Text>
            </Alert>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- Persisted Preferences -->
    <Stack>
        <Stack Gap="4">
            <Heading Level="2">Persisted Preferences</Heading>
            <Lumeo.Text Size="sm" Color="muted" Leading="relaxed">
                Theme preferences are automatically saved to
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">localStorage</code>
                whenever you call <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">SetModeAsync</code>,
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ToggleModeAsync</code>, or
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">SetSchemeAsync</code>.
                When the user returns, <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">InitializeAsync()</code>
                reads the stored values and restores the last-used theme.
            </Lumeo.Text>

            <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">localStorage Key</th>
                            <th class="text-left p-3 font-medium text-foreground">Example Value</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">lumeo-theme-mode</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">"dark"</td>
                            <td class="p-3 text-muted-foreground">The user's preferred mode (light, dark, or system).</td>
                        </tr>
                        <tr>
                            <td class="p-3 font-mono text-xs text-primary">lumeo-theme-scheme</td>
                            <td class="p-3 font-mono text-xs text-muted-foreground">"blue"</td>
                            <td class="p-3 text-muted-foreground">The user's preferred color scheme ID.</td>
                        </tr>
                    </tbody>
                </table>
            </Stack>

            <Lumeo.Text Size="sm" Color="muted">
                No server-side storage is required. If no preference is found, the service defaults to
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">ThemeMode.System</code> and the
                <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">"zinc"</code> color scheme.
            </Lumeo.Text>
        </Stack>
    </Stack>

    <Separator Class="my-4" />

    <!-- API Reference -->
    <Stack>
        <Stack Gap="6">
            <Heading Level="2">API Reference</Heading>

            <!-- Properties -->
            <Stack>
                <Heading Level="3" Class="mb-3">Properties</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">Description</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-border/40">
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">CurrentMode</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">ThemeMode</td>
                                <td class="p-3 text-muted-foreground">The active mode: System, Light, or Dark.</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">CurrentScheme</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                                <td class="p-3 text-muted-foreground">The active color scheme ID (e.g. "zinc", "blue").</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">IsDark</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">bool</td>
                                <td class="p-3 text-muted-foreground">Whether dark mode is currently active. Reflects the resolved state (including System mode detection).</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">AvailableSchemes</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">IReadOnlyList&lt;ThemeSchemeInfo&gt;</td>
                                <td class="p-3 text-muted-foreground">Static list of all built-in color schemes with their ID, display name, and preview color.</td>
                            </tr>
                        </tbody>
                    </table>
                </Stack>
            </Stack>

            <!-- Methods -->
            <Stack>
                <Heading Level="3" Class="mb-3">Methods</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">Method</th>
                                <th class="text-left p-3 font-medium text-foreground">Returns</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">InitializeAsync()</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">Task</td>
                                <td class="p-3 text-muted-foreground">Reads persisted preferences from localStorage and applies them. Call once in OnAfterRenderAsync.</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">SetModeAsync(ThemeMode)</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">Task</td>
                                <td class="p-3 text-muted-foreground">Sets the mode to System, Light, or Dark. Persists the choice and fires OnThemeChanged.</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">ToggleModeAsync()</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">Task</td>
                                <td class="p-3 text-muted-foreground">Toggles between light and dark mode. Persists the choice and fires OnThemeChanged.</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">SetSchemeAsync(string)</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">Task</td>
                                <td class="p-3 text-muted-foreground">Changes the active color scheme by ID (e.g. "blue"). Persists the choice and fires OnThemeChanged.</td>
                            </tr>
                        </tbody>
                    </table>
                </Stack>
            </Stack>

            <!-- Events -->
            <Stack>
                <Heading Level="3" Class="mb-3">Events</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">Event</th>
                                <th class="text-left p-3 font-medium text-foreground">Type</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">OnThemeChanged</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">Action?</td>
                                <td class="p-3 text-muted-foreground">Fired after any mode or scheme change. Subscribe in OnInitialized, unsubscribe in Dispose().</td>
                            </tr>
                        </tbody>
                    </table>
                </Stack>
            </Stack>

            <!-- ThemeMode Enum -->
            <Stack>
                <Heading Level="3" Class="mb-3">ThemeMode Enum</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">Value</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">System</td>
                                <td class="p-3 text-muted-foreground">Follows the operating system's light/dark preference via <code class="rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-foreground">prefers-color-scheme</code>.</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">Light</td>
                                <td class="p-3 text-muted-foreground">Forces light mode regardless of OS setting.</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">Dark</td>
                                <td class="p-3 text-muted-foreground">Forces dark mode regardless of OS setting.</td>
                            </tr>
                        </tbody>
                    </table>
                </Stack>
            </Stack>

            <!-- ThemeSchemeInfo Record -->
            <Stack>
                <Heading Level="3" Class="mb-3">ThemeSchemeInfo Record</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">Description</th>
                            </tr>
                        </thead>
                        <tbody class="divide-y divide-border/40">
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">Id</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                                <td class="p-3 text-muted-foreground">Unique identifier for the scheme (e.g. "zinc", "blue").</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">DisplayName</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                                <td class="p-3 text-muted-foreground">Human-readable name (e.g. "Orange", "Blue").</td>
                            </tr>
                            <tr>
                                <td class="p-3 font-mono text-xs text-primary">PreviewColor</td>
                                <td class="p-3 font-mono text-xs text-muted-foreground">string</td>
                                <td class="p-3 text-muted-foreground">CSS color value for preview swatches (e.g. "hsl(14 70% 50%)").</td>
                            </tr>
                        </tbody>
                    </table>
                </Stack>
            </Stack>

        </Stack>
    </Stack>

</Stack>

@code {
    protected override void OnInitialized()
    {
        ThemeService.OnThemeChanged += HandleThemeChanged;
    }

    private void HandleThemeChanged()
    {
        _ = InvokeAsync(StateHasChanged);
    }

    private async Task HandleToggle()
    {
        await ThemeService.ToggleModeAsync();
    }

    public void Dispose()
    {
        ThemeService.OnThemeChanged -= HandleThemeChanged;
    }
}

