/// Configuration options for initializing a Ziex project in your build.zig.
///
/// This struct provides comprehensive control over how Ziex transpiles and builds
/// your website, including CLI configuration, experimental features, and plugin integration.
///
/// ## Usage Example
/// ```zig
/// const ziex_options: ziex.InitOptions = .{
///     .site = .{ .path = "site" },
///     .cli = .{
///         .path = null, // Use Ziex from dependency
///         .steps = .{
///             .dev = "dev",
///             .serve = "serve",
///         },
///     },
/// };
/// try ziex.init(b, exe, ziex_options);
/// ```
const std = @import("std");
const LazyPath = std.Build.LazyPath;

/// Configuration for the Ziex CLI executable and build steps.
pub const CliOptions = struct {
    /// Custom names for Ziex build steps.
    ///
    /// Configure which Zig build steps to create and what names to give them.
    /// Set any step to `null` to disable it.
    pub const Steps = struct {
        /// Step name for development mode with hot-reload (default: null/disabled)
        dev: ?[]const u8 = null,
        /// Step name for running the site in production build without hot-reload (default: "serve")
        serve: ?[]const u8 = null,
        /// Step name for exporting static site (default: null/disabled)
        @"export": ?[]const u8 = null,
        /// Step name for bundling the website (default: null/disabled)
        bundle: ?[]const u8 = null,

        pub const default: Steps = .{ .dev = "dev", .serve = "serve" };
    };

    /// Path to the ZX CLI executable.
    ///
    /// - If `null`: Uses the ZX CLI from the ZX dependency source (recommended)
    /// - If set to `"zx"`: Uses the ZX CLI from the system PATH
    /// - Otherwise: Uses the specified path to a ZX CLI executable
    path: ?LazyPath = null,

    /// Configuration for which build steps to create.
    ///
    /// If `null`, only the default "serve" step will be created.
    steps: ?Steps = .default,

    /// Optimize mode for the ZX CLI executable.
    optimize: ?std.builtin.OptimizeMode = .ReleaseFast,
};

/// Configuration for the ZX app directory.
pub const AppOptions = struct {
    pub const FeatureOptions = struct {
        /// Embedded SQLite database, exposed at runtime as `zx.db`.
        pub const SqliteOptions = struct {
            pub const SqliteServerOptions = struct {
                pub const enabled: SqliteServerOptions = .{};
            };
            pub const enabled: SqliteOptions = .{ .server = .enabled };

            server: ?SqliteServerOptions = null,
        };

        /// Filesystem-backed key/value store, exposed at runtime as `zx.kv`.
        pub const KvOptions = struct {
            pub const KvServerOptions = struct {
                pub const enabled: KvServerOptions = .{};
            };
            pub const KvClientOptions = struct {
                pub const enabled: KvClientOptions = .{};
            };
            pub const enabled: KvOptions = .{ .server = .enabled, .client = .enabled };

            server: ?KvServerOptions = null,
            client: ?KvClientOptions = null,
        };

        /// Filesystem-backed cache (used by component-level caching),
        /// exposed at runtime as `zx.cache`.
        pub const CacheOptions = struct {
            pub const CacheServerOptions = struct {
                pub const enabled: CacheServerOptions = .{};
            };
            pub const enabled: CacheOptions = .{ .server = .enabled };

            server: ?CacheServerOptions = null,
        };

        pub const default = FeatureOptions{};

        sqlite: ?SqliteOptions = null,
        kv: ?KvOptions = null,
        cache: ?CacheOptions = null,
    };

    /// Path to the ZX app source directory.
    ///
    /// This directory should contain your `.zx` template files, layouts,
    /// and other app assets. Defaults to "app" if not specified in InitOptions.
    path: ?LazyPath = null,

    /// Base path for all routes in your app (e.g. if your app is served from "/blog", set this to "/blog").
    ///
    /// This will be used to prefix all route URLs and asset paths in your app.
    /// If `null`, defaults to root path ("/").
    base_path: ?[]const u8 = null,

    /// Features that can be optionally enabled
    features: FeatureOptions = .default,
};

pub const ClientOptions = struct {
    pub const default: ClientOptions = .{};

    jsglue_href: ?[]const u8 = null,
    wasm_href: ?[]const u8 = null,

    /// Install the JS-glue package source (the `ziex_js` npm package) into a
    /// subdirectory under the install prefix (`zig-out/<subdir>`).
    ///
    /// Ziex auto-injects the JS glue at runtime for normal server deployments,
    /// so this is `null` (no install) by default. Set it for platforms that
    /// need the package available on disk to install it themselves — e.g. Vercel
    jsglue_install_subdir: ?[]const u8 = null,
};

/// Experimental features that may change in future versions.
const ExperimentalOptions = struct {};

/// App directory configuration.
///
/// If `null`, defaults to `app` directory in your project root.
/// Override this to use a custom app source directory.
app: ?AppOptions = null,

/// ZX CLI configuration.
///
/// Controls which ZX CLI executable to use and which build steps to create.
/// If `null`, uses default configuration with ZX CLI from dependency source.
cli: CliOptions = .{},

/// Enable Client-Side Rendering (CSR) support.
///
/// When enabled, ZX will compile a WebAssembly module for client-side
/// interactivity and hydration. This generates additional build artifacts
/// in the assets directory.
client: ClientOptions = .default,

/// Experimental features configuration.
///
/// Enable cutting-edge ZX features that may have breaking changes in the future.
/// If `null`, all experimental features are disabled.
experimental: ?ExperimentalOptions = null,

/// Build-time output location for compiled assets and public files.
///
/// This controls only where the build *emits* assets. The location the
/// *running app* serves static files and stores data from is controlled at
/// runtime by the `ZIEX_STATIC_DIR` and `ZIEX_DATA_DIR` environment variables.
///
/// If `null`, defaults to `zig-out/static` in your project root.
static_path: ?LazyPath = null,

/// Version string used for cache-busting asset URLs (e.g. `/assets/_/main.wasm?<version>`).
///
/// Pass your app's version here so that asset URLs change when you ship a new release:
/// ```zig
/// .version = @import("build.zig.zon").version,
/// ```
/// If `null`, falls back to ziex's own version.
version: ?[]const u8 = null,
