#!/usr/bin/env perl
use strict;
use warnings;

use PAGI::Runner;

PAGI::Runner->run(@ARGV);

__END__

=encoding UTF-8

=head1 NAME

pagi-server - PAGI application server

=head1 SYNOPSIS

    pagi-server [options] [app] [key=value ...]

    # Serve current directory (default)
    pagi-server

    # Serve a specific directory
    pagi-server PAGI::App::Directory root=/var/www

    # Run a PAGI app file
    pagi-server ./app.pl

    # With environment modes
    pagi-server -E development app.pl  # Lint middleware enabled
    pagi-server -E production app.pl   # No auto-middleware

    # With options
    pagi-server -p 8080 PAGI::App::Directory root=/var/www
    pagi-server --workers 4 ./myapp.pl

=head1 DESCRIPTION

pagi-server is the command-line interface for running PAGI applications.
It uses L<PAGI::Runner> for application loading and server orchestration,
and L<PAGI::Server> as the default server backend.

=head1 ENVIRONMENT MODES

pagi-server supports environment modes similar to Plack's C<-E> flag:

=over 4

=item B<development>

Auto-enables L<PAGI::Middleware::Lint> with strict mode. This catches
specification violations early and provides helpful error messages.

This is the B<default when running interactively> (TTY detected).

=item B<production>

No middleware is auto-enabled, and access logging is disabled for maximum
performance. Use C<--access-log FILE> to enable logging in production.

This is the B<default when running non-interactively> (no TTY, e.g.,
systemd, docker, cron).

=item B<none>

Explicit opt-out of all auto-middleware, regardless of TTY detection.

=back

Mode is determined by (in order of precedence):

    1. -E / --env command line flag
    2. PAGI_ENV environment variable
    3. Auto-detection: TTY = development, no TTY = production

=head1 OPTIONS

=head2 Common Options

These are handled by L<PAGI::Runner> and work with any server backend.

=over 4

=item B<-I>, B<--lib> PATH

Add PATH to C<@INC> before loading the app. Can be specified multiple
times, similar to C<perl -I>.

    pagi-server -I ./lib -I ./vendor/lib ./app.pl

=item B<-a>, B<--app> FILE

Path to .pl/.psgi file returning PAGI app coderef. Legacy option for
backward compatibility; you can also just pass the file as an argument.

=item B<-e> CODE

Inline app code, like C<perl -e>. Must return a PAGI app coderef.

    # Using a PAGI::App module
    pagi-server -MPAGI::App::File -e 'PAGI::App::File->new(root => ".")->to_app'

=item B<-M> MODULE

Load MODULE before evaluating C<-e> code, like C<perl -M>. Can be
specified multiple times. Supports C<Module=import,args> syntax.

    pagi-server -MPAGI::App::File -e 'PAGI::App::File->new(root => ".")->to_app'

=item B<-o>, B<--host> HOST

Bind address (default: 127.0.0.1, localhost only)

The default only accepts connections from localhost, which is B<secure by
default> for development. For remote access:

    pagi-server --host 0.0.0.0 ./app.pl    # All IPv4 interfaces

=item B<-p>, B<--port> PORT

Bind port (default: 5000)

=item B<-s>, B<--server> CLASS

Server class to use (default: PAGI::Server). Reserved for future use
with pluggable server backends.

=item B<-E>, B<--env> MODE

Environment mode: development, production, or none.

=item B<-l>, B<--loop> BACKEND

Event loop backend (Poll, EV, Epoll, UV). Default is auto-detect.

=item B<--access-log> FILE

Path to access log file (default: STDERR)

=item B<--no-access-log>

Disable access logging entirely. Improves throughput by 5-15%.

=item B<-D>, B<--daemonize>

Fork to background and run as a daemon.

=item B<--pid> FILE

Write the process ID to FILE.

=item B<--user> USER

After binding, drop privileges to run as USER. Requires root.

=item B<--group> GROUP

After binding, drop privileges to run as GROUP.

=item B<-q>, B<--quiet>

Suppress startup banner and development mode message.

=item B<--no-default-middleware>

Disable auto-middleware even in development mode.

=item B<-v>, B<--version>

Show version info.

=item B<--help>

Show help.

=back

=head2 PAGI::Server Options

These options are passed through to L<PAGI::Server>.

=over 4

=item B<-w>, B<--workers> NUM

Number of worker processes (default: 1, single-process mode)

=item B<--reuseport>

Enable SO_REUSEPORT mode for multi-worker servers.

=item B<--ssl-cert> FILE, B<--ssl-key> FILE

Enable HTTPS with the specified certificate and key files.

=item B<--max-requests> NUM

Maximum requests per worker before restart (default: 0, unlimited)

=item B<--max-connections> NUM

Maximum concurrent connections per worker (default: auto-detect)

=item B<--max-body-size> NUM

Maximum request body size in bytes (default: 10MB)

=item B<--timeout> NUM

Connection idle timeout in seconds (default: 60)

=item B<--shutdown-timeout> NUM

Graceful shutdown timeout in seconds (default: 30)

=item B<--log-level> LEVEL

Log verbosity: debug, info, warn, error (default: info)

=item B<-b>, B<--listener-backlog> NUM

Listen queue size (default: 2048)

=item B<--max-receive-queue> NUM

Maximum WebSocket receive queue size (default: 1000)

=item B<--max-ws-frame-size> NUM

Maximum WebSocket frame size in bytes (default: 65536)

=item B<--request-timeout> NUM

Request stall timeout in seconds (default: 0, disabled)

=item B<--ws-idle-timeout> NUM

WebSocket idle timeout in seconds (default: 0, disabled)

=item B<--sse-idle-timeout> NUM

SSE idle timeout in seconds (default: 0, disabled)

=item B<--sync-file-threshold> NUM

Sync file read threshold in bytes (default: 65536)

=back

=head1 APP SPECIFICATION

=head2 Module Name

If the argument contains C<::>, it's treated as a Perl module name:

    pagi-server PAGI::App::Directory root=/var/www

The module must have C<new()> and C<to_app()> methods.

=head2 File Path

If the argument contains C</> or ends with C<.pl>/C<.psgi>:

    pagi-server ./app.pl

The file must return a PAGI app coderef.

=head2 Default

If no app is specified, serves the current directory:

    pagi-server
    # equivalent to: pagi-server PAGI::App::Directory root=.

=head1 SIGNAL HANDLING

=over 4

=item B<TERM>, B<INT>

Graceful shutdown.

=item B<HUP>

Graceful restart (multi-worker mode only).

=item B<TTIN>, B<TTOU>

Increase/decrease worker count (multi-worker mode only).

=back

=head1 EXAMPLES

    # Development (auto-detected from TTY)
    pagi-server ./app.pl

    # Explicit production mode
    pagi-server -E production ./app.pl
    PAGI_ENV=production pagi-server ./app.pl

    # Multi-worker production
    pagi-server --host 0.0.0.0 -p 80 --workers 4 -E production ./app.pl

    # With HTTPS
    pagi-server --ssl-cert cert.pem --ssl-key key.pem ./app.pl

    # Maximum performance
    pagi-server --no-access-log --workers 8 -E production ./app.pl

    # Using EV event loop
    pagi-server --loop EV ./app.pl

=head1 ENVIRONMENT

=over 4

=item B<PAGI_ENV>

Default environment mode if C<-E> is not specified and no TTY detected.

=item B<IO_ASYNC_LOOP>

Preferred IO::Async loop backend.

=back

=head1 SEE ALSO

L<PAGI::Runner>, L<PAGI::Server>, L<PAGI::Middleware::Lint>

=head1 AUTHOR

John Napiorkowski E<lt>jjnapiork@cpan.orgE<gt>

=head1 LICENSE

This software is licensed under the same terms as Perl itself.

=cut
