var count: i32 = 0;
pub fn Page(ctx: zx.PageContext) zx.Component {
    count += 1;
    ctx.response.cookies.set("count", std.fmt.allocPrint(ctx.arena, "{d}", .{count}) catch unreachable, .{});
    if (count == 4) {
        ctx.response.cookies.delete("count", .{});
        count = 0;
    }

    const count_cookie = ctx.request.cookies.get("count");
    if (count_cookie) |cookie| {
        ctx.response.cookies.set("count-old", cookie, .{});
    }
    const allocator = ctx.arena;

    // For Loop example
    var aw_for: std.io.Writer.Allocating = .init(allocator);
    const zx_for = @embedFile("./sandbox/for_loop.zx");
    const zig_for = @embedFile("./sandbox/for_loop.zig");
    const html_page_for = @import("./sandbox/for_loop.zig").Page(allocator);
    html_page_for.render(&aw_for.writer) catch unreachable;
    const html_for = allocator.dupe(u8, aw_for.written()) catch unreachable;

    // If/Else example
    var aw_if: std.io.Writer.Allocating = .init(allocator);
    const zx_if = @embedFile("./sandbox/if_else.zx");
    const zig_if = @embedFile("./sandbox/if_else.zig");
    const html_page_if = @import("./sandbox/if_else.zig").Page(allocator);
    html_page_if.render(&aw_if.writer) catch unreachable;
    const html_if = allocator.dupe(u8, aw_if.written()) catch unreachable;

    // Switch example
    var aw_switch: std.io.Writer.Allocating = .init(allocator);
    const zx_switch = @embedFile("./sandbox/switch_expr.zx");
    const zig_switch = @embedFile("./sandbox/switch_expr.zig");
    const html_page_switch = @import("./sandbox/switch_expr.zig").Page(allocator);
    html_page_switch.render(&aw_switch.writer) catch unreachable;
    const html_switch = allocator.dupe(u8, aw_switch.written()) catch unreachable;

    // Form example
    var aw_form: std.io.Writer.Allocating = .init(allocator);
    const zx_form = @embedFile("./sandbox/form_handling.zx");
    const zig_form = @embedFile("./sandbox/form_handling.zig");
    const html_page_form = @import("./sandbox/form_handling.zig").Page(allocator);
    html_page_form.render(&aw_form.writer) catch unreachable;
    const html_form = allocator.dupe(u8, aw_form.written()) catch unreachable;

    // Components example
    var aw_components: std.io.Writer.Allocating = .init(allocator);
    const zx_components = @embedFile("./sandbox/components.zx");
    const zig_components = @embedFile("./sandbox/components.zig");
    const html_page_components = @import("./sandbox/components.zig").Page(allocator);
    html_page_components.render(&aw_components.writer) catch unreachable;
    const html_components = allocator.dupe(u8, aw_components.written()) catch unreachable;

    // Dynamic attributes example
    var aw_dynattr: std.io.Writer.Allocating = .init(allocator);
    const zx_dynattr = @embedFile("./sandbox/dynamic_attr.zx");
    const zig_dynattr = @embedFile("./sandbox/dynamic_attr.zig");
    const html_page_dynattr = @import("./sandbox/dynamic_attr.zig").Page(allocator);
    html_page_dynattr.render(&aw_dynattr.writer) catch unreachable;
    const html_dynattr = allocator.dupe(u8, aw_dynattr.written()) catch unreachable;

    return (
        <fragment @allocator={allocator}>
            <ExamplesHeader />
            <IfElseSection zx_code={zx_if} zig_code={zig_if} html_code={html_if} />
            <SwitchSection zx_code={zx_switch} zig_code={zig_switch} html_code={html_switch} />
            <ForLoopSection zx_code={zx_for} zig_code={zig_for} html_code={html_for} />
            <ComponentsSection zx_code={zx_components} zig_code={zig_components} html_code={html_components} />
            <DynamicAttrSection zx_code={zx_dynattr} zig_code={zig_dynattr} html_code={html_dynattr} />
            <FormSection zx_code={zx_form} zig_code={zig_form} html_code={html_form} />
            <CachingSection />

            <div style="display: none">
                <RenderTest />
            </div>
        </fragment>
    );
}

fn ExamplesHeader(allocator: zx.Allocator) zx.Component {
    return (
        <section class="section learn-header" @allocator={allocator}>
            <p class="section-category">ZX Framework</p>
            <h1>Examples</h1>
            <p class="lead">Explore the examples showcasing use of ZX in different scenarios. Each example includes the codes and it's preview.</p>
        </section>
    );
}

const ExampleSectionProps = struct {
    zx_code: []const u8,
    zig_code: []const u8,
    html_code: []const u8,
};

fn IfElseSection(allocator: zx.Allocator, props: ExampleSectionProps) zx.Component {
    return (
        <section id="if-else" class="section" @allocator={allocator}>
            <h2>If/Else Statements</h2>
            <p>Use if/else expressions to conditionally render content based on state. ZX supports inline conditional expressions that return components or text.</p>
            <ExampleBlock id="if-else-example" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="if_else.zx" />
            <div class="callout tip">
                <strong>Tip:</strong> You can nest if/else expressions for more complex conditional logic.
            </div>
        </section>
    );
}

fn SwitchSection(allocator: zx.Allocator, props: ExampleSectionProps) zx.Component {
    return (
        <section id="switch" class="section" @allocator={allocator}>
            <h2>Switch Expressions</h2>
            <p>Switch expressions provide pattern matching for enums and other types. Each branch can return a component or text.</p>
            <ExampleBlock id="switch-example" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="switch_expr.zx" />
        </section>
    );
}

fn ForLoopSection(allocator: zx.Allocator, props: ExampleSectionProps) zx.Component {
    return (
        <section id="for-loop" class="section" @allocator={allocator}>
            <h2>For Loop</h2>
            <p>Iterate over arrays and slices to render lists of components. Each iteration receives the current item which you can use in your template.</p>
            <ExampleBlock id="for-loop-example" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="for_loop.zx" />
        </section>
    );
}

fn ComponentsSection(allocator: zx.Allocator, props: ExampleSectionProps) zx.Component {
    return (
        <section id="components" class="section" @allocator={allocator}>
            <h2>Component Props</h2>
            <p>Create reusable components by defining props structs. Components can accept any Zig type as props, including booleans, strings, and custom structs.</p>
            <ExampleBlock id="components-example" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="components.zx" />
        </section>
    );
}

fn DynamicAttrSection(allocator: zx.Allocator, props: ExampleSectionProps) zx.Component {
    return (
        <section id="dynamic-attributes" class="section" @allocator={allocator}>
            <h2>Dynamic Attributes</h2>
            <p>Set HTML attributes dynamically using Zig expressions. Boolean attributes like <code>disabled</code> and <code>readonly</code> are handled automatically.</p>
            <ExampleBlock id="dynamic-attr-example" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="dynamic_attr.zx" />
        </section>
    );
}

fn FormSection(allocator: zx.Allocator, props: ExampleSectionProps) zx.Component {
    return (
        <section id="form-handling" class="section" @allocator={allocator}>
            <h2>Form Handling</h2>
            <p>Build forms with standard HTML form elements. ZX handles form submission through standard HTTP methods.</p>
            <ExampleBlock id="form-example" zx_code={props.zx_code} zig_code={props.zig_code} html_code={props.html_code} filename="form_handling.zx" />
        </section>
    );
}

fn CachingSection(allocator: zx.Allocator) zx.Component {
    // Component caching examples
    const component_caching_example =
        \\// Cache a component for 10 seconds
        \\fn Page(allocator: zx.Allocator) zx.Component {
        \\    return (
        \\        <div @allocator={allocator}>
        \\            <Header @caching="1h" />
        \\            <Content />
        \\            <Sidebar @caching="30m:sidebar" />
        \\        </div>
        \\    );
        \\}
        \\
        \\fn Header(allocator: zx.Allocator) zx.Component {
        \\    return (<header @allocator={allocator}>Site Header</header>);
        \\}
        \\
        \\fn Sidebar(allocator: zx.Allocator) zx.Component {
        \\    return (<aside @allocator={allocator}>Sidebar</aside>);
        \\}
    ;

    const page_caching_example =
        \\pub fn Page(ctx: zx.PageContext) zx.Component {
        \\    return (
        \\        <div @allocator={ctx.arena}>
        \\            <h1>Cached Page</h1>
        \\            <p>This entire page is cached for 5 minutes.</p>
        \\            <p>Current time: {std.time.timestamp()}</p>
        \\        </div>
        \\    );
        \\}
        \\
        \\// Page-level caching configuration
        \\pub const options = zx.PageOptions{
        \\    .caching = .{ .seconds = 300 }, // 5 minutes
        \\};
    ;

    const layout_caching_example =
        \\pub fn Layout(ctx: zx.LayoutContext, children: zx.Component) zx.Component {
        \\    return (
        \\        <html @allocator={ctx.arena}>
        \\            <head><title>My Site</title></head>
        \\            <body>
        \\                <nav>Navigation</nav>
        \\                <main>{children}</main>
        \\                <footer>Footer</footer>
        \\            </body>
        \\        </html>
        \\    );
        \\}
        \\
        \\// Layout caching (caches entire layout including children)
        \\pub const options = zx.LayoutOptions{
        \\    .caching = .{ .seconds = 3600 }, // 1 hour
        \\};
    ;

    return (
        <section id="caching" class="section" @allocator={allocator}>
            <h2>Caching <span class="badge">Alpha</span></h2>
            <p>ZX provides built-in caching at multiple levels to improve performance. Cache rendered HTML and serve it directly without re-rendering.</p>

            <h3 id="caching-components">Component Caching</h3>
            <p>Use the <code>@caching</code> attribute to cache individual components. Specify duration with units: <code>s</code> (seconds), <code>m</code> (minutes), <code>h</code> (hours), or <code>d</code> (days). Add a key after <code>:</code> for manual invalidation.</p>
            <CodeBlock code={component_caching_example} filename="component_caching.zx" />

            <h3 id="caching-pages">Page Caching</h3>
            <p>Cache entire pages by exporting <code>options</code> with caching configuration. The server automatically adds <code>ETag</code> and <code>Cache-Control</code> headers.</p>
            <CodeBlock code={page_caching_example} filename="cached_page.zx" />

            <h3 id="caching-layouts">Layout Caching</h3>
            <p>Layouts can also be cached. Be careful: this caches the entire layout including page content.</p>
            <CodeBlock code={layout_caching_example} filename="cached_layout.zx" />

            <div class="callout tip">
                <strong>Tip:</strong> Use <code>zx.cache.del("cmp:key")</code> or <code>zx.cache.delPrefix("cmp:prefix")</code> to manually invalidate cached content when data changes.
            </div>
        </section>
    );
}

const RenderTest = feature_examples.RenderTest;

const std = @import("std");
const CodeBlock = @import("../components/code_block.zx").CodeBlock;
const zx = @import("zx");
const Sidebar = @import("../components/sidebar.zx").Sidebar;
const SidebarProps = @import("../components/sidebar.zx").SidebarProps;
const ExampleBlock = @import("../components/example_block.zx").ExampleBlock;
const feature_examples = @import("feature_examples.zx");
