//! The `gize` command tree (ADR-012). Parsing only — each command delegates to a handler
//! in [`crate::commands`].

use clap::{Args, Parser, Subcommand};

#[derive(Debug, Parser)]
#[command(
    name = "gize",
    version,
    about = "Productivity-first backend framework for Rust"
)]
pub struct Cli {
    #[command(subcommand)]
    pub command: Command,
}

/// Flags shared by every generating command (ADR-012 safety model).
#[derive(Debug, Args, Clone, Copy, Default)]
pub struct GenFlags {
    /// Overwrite existing files instead of skipping them.
    #[arg(long, global = true)]
    pub force: bool,
    /// Show what would be written without touching the filesystem.
    #[arg(long, global = true)]
    pub dry_run: bool,
}

#[derive(Debug, Subcommand)]
pub enum Command {
    /// Scaffold a new project.
    New {
        /// Project name (also the directory created).
        name: String,
        /// Skip the built-in `users` resource (model, CRUD and migration).
        #[arg(long)]
        no_user: bool,
        /// Generate an OpenAPI spec (`/openapi.json`) and docs UI (`/docs`).
        #[arg(long)]
        openapi: bool,
        /// Scaffold a WebSocket module (`src/app/ws/`) with a typed echo endpoint (ADR-018).
        #[arg(long)]
        ws: bool,
        /// Target database: `postgres` (default), `sqlite` or `mysql` (ADR-015).
        #[arg(long, default_value = "postgres")]
        database: String,
        /// Mount CRUD routes under a versioned API prefix, e.g. `--api-version 1` (or `v1`)
        /// serves them at `/api/v1/...`. Omit for root-mounted routes (ADR-016).
        #[arg(long)]
        api_version: Option<String>,
        #[command(flatten)]
        flags: GenFlags,
    },
    /// Generate application pieces (app, model, crud, migration, admin).
    #[command(subcommand)]
    Make(MakeCommand),
    /// Create the first admin user in the database (ADR-017). Interactive by default; pass
    /// `--email`/`--name` and `--password-env` for non-interactive/CI use.
    Createadmin {
        /// Admin email. Prompted for if omitted.
        #[arg(long)]
        email: Option<String>,
        /// Admin display name (the `users.name` column). Prompted for if omitted.
        #[arg(long)]
        name: Option<String>,
        /// Read the password from this environment variable instead of prompting (for CI).
        /// The password is never accepted as a direct argument.
        #[arg(long, value_name = "VAR")]
        password_env: Option<String>,
    },
    /// Apply pending database migrations.
    Migrate {
        /// Show applied/pending migrations instead of applying.
        #[arg(long)]
        status: bool,
    },
    /// Run the generated application, and (by default, when an admin exists) its admin dev
    /// server (ADR-019).
    Serve {
        /// Run only the API — do not start the admin dev server.
        #[arg(long, conflicts_with_all = ["admin_only", "with_admin"])]
        api_only: bool,
        /// Run only the admin dev server — do not start the API.
        #[arg(long, conflicts_with_all = ["api_only", "with_admin"])]
        admin_only: bool,
        /// Explicitly start the admin dev server alongside the API (the default when an admin
        /// has been generated).
        #[arg(long, conflicts_with_all = ["api_only", "admin_only"])]
        with_admin: bool,
    },
    /// Reconcile the project from gize.toml.
    Sync {
        #[command(flatten)]
        flags: GenFlags,
    },
    /// Diagnose the environment and project.
    Doctor,
    /// Format the project (wrapper around rustfmt).
    Fmt,
    /// Check the project (wrapper around clippy/check).
    Check,
    /// A plugin subcommand: `gize <name> …` runs the `gize-<name>` executable on PATH
    /// (ADR-008, v0). The first element is the plugin name, the rest are its arguments.
    #[command(external_subcommand)]
    External(Vec<String>),
}

#[derive(Debug, Subcommand)]
pub enum MakeCommand {
    /// Create a new application module.
    App {
        name: String,
        #[command(flatten)]
        flags: GenFlags,
    },
    /// Generate a model from `field:Type` definitions.
    Model {
        /// Model name in PascalCase, e.g. `User`.
        name: String,
        /// Field definitions: `name:String email:String active:bool`.
        fields: Vec<String>,
        #[command(flatten)]
        flags: GenFlags,
    },
    /// Generate full CRUD (repository, service, dto, handlers, routes, tests) for a model.
    Crud {
        /// Model name in PascalCase, e.g. `Product`.
        name: String,
        /// Field definitions: `name:String price:i32 active:bool`.
        fields: Vec<String>,
        #[command(flatten)]
        flags: GenFlags,
    },
    /// Generate a database migration.
    Migration {
        /// Optional migration name.
        name: Option<String>,
        #[command(flatten)]
        flags: GenFlags,
    },
    /// Generate the admin SPA (a separate Vite + React app) for all resources (Beta).
    Admin {
        /// Optional resource name (informational; the admin is generated for every resource).
        name: Option<String>,
        #[command(flatten)]
        flags: GenFlags,
    },
}
