var overview_component_count: usize = 0;
var overview_route_count: usize = 0;

var components_fetch_started = false;
var routes_fetch_started = false;

fn ensureCountsFetch() void {
    if (!data.loadSettings()) return;
    fetchComponentsCount();
    fetchRoutesCount();
}

fn fetchComponentsCount() void {
    if (components_fetch_started) return;
    const host = data.host;
    const path = data.current_path;
    const base = if (std.mem.startsWith(u8, host, "http://") or std.mem.startsWith(u8, host, "https://")) host else std.fmt.allocPrint(zx.client_allocator, "http://{s}", .{host}) catch return;
    const url = std.fmt.allocPrint(zx.client_allocator, "{s}/.well-known/_zx/devtool?path={s}", .{ base, path }) catch return;
    components_fetch_started = true;
    _ = zx.fetch(.wasm(&onFetchComponentsCount), zx.client_allocator, url, .{ .method = .GET }) catch {};
}

fn fetchRoutesCount() void {
    if (routes_fetch_started) return;
    const host = data.host;
    const base = if (std.mem.startsWith(u8, host, "http://") or std.mem.startsWith(u8, host, "https://")) host else std.fmt.allocPrint(zx.client_allocator, "http://{s}", .{host}) catch return;
    const url = std.fmt.allocPrint(zx.client_allocator, "{s}/.well-known/_zx/devtool?meta=true", .{base}) catch return;
    routes_fetch_started = true;
    _ = zx.fetch(.wasm(&onFetchRoutesCount), zx.client_allocator, url, .{ .method = .GET }) catch {};
}

fn onFetchComponentsCount(res: ?*zx.Fetch.Response, _: ?zx.Fetch.FetchError) void {
    if (res) |r| {
        defer r.deinit();
        if (r.text()) |p| {
            const parsed = zx.util.zxon.parse(zx.Component.Serializable, zx.client_allocator, p, .{}) catch return;
            overview_component_count = countSerializable(parsed.children orelse &.{}, 0);
        } else |_| {}
    }
    zx.client.rerender();
}

fn countSerializable(nodes: []const zx.Component.Serializable, acc: usize) usize {
    var total = acc;
    for (nodes) |n| {
        total += 1;
        if (n.children) |kids| {
            total = countSerializable(kids, total);
        }
    }
    return total;
}

const AppRoute = struct {
    path: []const u8,
    kind: []const u8 = "Page",
    methods: []const []const u8 = &.{},
    has_notfound: bool = false,
    is_dynamic: bool = false,
};

fn onFetchRoutesCount(res: ?*zx.Fetch.Response, _: ?zx.Fetch.FetchError) void {
    if (res) |r| {
        defer r.deinit();
        if (r.text()) |p| {
            const parsed = zx.util.zxon.parse([]const AppRoute, zx.client_allocator, p, .{}) catch return;
            overview_route_count = parsed.len;
        } else |_| {}
    }
    zx.client.rerender();
}

pub fn Page(ctx: zx.PageContext) zx.Component {
    return (
        <div @allocator={ctx.arena} class="overview-container">
            <div class="banner">
                <div class="hero-content">
                    <div class="hero-title-wrapper">
                        <h1 class="hero-title-main">Ziex</h1>
                        <div class="hero-title-accent">/</div>
                    </div>

                    <p class="hero-subtitle">
                        Ziex DevTools
                    </p>
                    <p class="hero-description">
                        Developer Tools for Ziex Framework
                        <code class="version-badge">{zx.info.version}</code>
                    </p>

                    <FeatureGrid @rendering={.client} />

                    <div class="quick-links">
                        <a href="https://github.com/nurulhudaapon/zx" target="_blank" class="link-item">
                            <span>{icons.Star(ctx.arena)} Star on GitHub</span>
                        </a>
                        <a href="https://ziex.dev" target="_blank" class="link-item">
                            <span>{icons.Document(ctx.arena)} Documentation</span>
                        </a>
                        <a href="https://github.com/nurulhudaapon/zx/issues" target="_blank" class="link-item">
                            <span>{icons.Bug(ctx.arena)} Report Issue</span>
                        </a>
                    </div>
                </div>
            </div>
        </div>
    );
}

const Feature = struct { icon_fn: *const fn (zx.Allocator) zx.Component, title: []const u8, link: []const u8 };
const FeatureGridProps = struct {};

pub fn FeatureGrid(ctx: *zx.ComponentCtx(FeatureGridProps)) zx.Component {
    ensureCountsFetch();
    return (
        <div @allocator={ctx.allocator} class="features-grid">
            <FeatureCard allocator={ctx.allocator} icon_fn={icons.Lightning} title={zx.info.version} link="overview" />
            <FeatureCard allocator={ctx.allocator} icon_fn={icons.Hive} title={getComponentCountLabel(ctx.allocator)} link="/" />
            <FeatureCard allocator={ctx.allocator} icon_fn={icons.Workflow} title={getRouteCountLabel(ctx.allocator)} link="routes" />
        </div>
    );
}
fn getComponentCountLabel(allocator: zx.Allocator) []const u8 {
    return std.fmt.allocPrint(allocator, "{d} components", .{overview_component_count}) catch "components";
}

fn getRouteCountLabel(allocator: zx.Allocator) []const u8 {
    return std.fmt.allocPrint(allocator, "{d} routes", .{overview_route_count}) catch "routes";
}

fn FeatureCard(allocator: zx.Allocator, props: Feature) zx.Component {
    const IconComponent = props.icon_fn(allocator);
    return (
        <a @allocator={allocator} class="feature-card" href={props.link}>
            <div class="feature-icon">{IconComponent}</div>
            <h3 class="feature-title">{props.title}</h3>
        </a>
    );
}

const std = @import("std");
const zx = @import("zx");
const icons = @import("../components/icons.zx");
const data = @import("../data.zig");
