#!/usr/bin/env node
/* eslint-disable no-console */

import openurl from 'openurl';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import localtunnel from '../localtunnel';
import { TunnelOptions } from '../types';

interface CliOptions extends Omit<TunnelOptions, 'local_host' | 'local_https' | 'local_cert' | 'local_key' | 'local_ca' | 'allow_invalid_cert'> {
  host: string;
  open?: boolean;
  'print-requests'?: boolean;
  help?: boolean;
  localHost?: string;
  localHttps?: boolean;
  localCert?: string;
  localKey?: string;
  localCa?: string;
  allowInvalidCert?: boolean;
}

const { version } = require('../../package.json');

const argv = yargs(hideBin(process.argv))
  .usage('Usage: lt --port [num] <options>')
  .env(true)
  .option('p', {
    alias: 'port',
    describe: 'Internal HTTP server port',
    type: 'number',
    demandOption: true,
  })
  .option('h', {
    alias: 'host',
    describe: 'Upstream server providing forwarding',
    default: 'https://localtunnel.me',
    type: 'string',
  })
  .option('s', {
    alias: 'subdomain',
    describe: 'Request this subdomain',
    type: 'string',
  })
  .option('l', {
    alias: 'local-host',
    describe: 'Tunnel traffic to this host instead of localhost, override Host header to this host',
    type: 'string',
  })
  .option('local-https', {
    describe: 'Tunnel traffic to a local HTTPS server',
    type: 'boolean',
  })
  .option('local-cert', {
    describe: 'Path to certificate PEM file for local HTTPS server',
    type: 'string',
  })
  .option('local-key', {
    describe: 'Path to certificate key file for local HTTPS server',
    type: 'string',
  })
  .option('local-ca', {
    describe: 'Path to certificate authority file for self-signed certificates',
    type: 'string',
  })
  .option('allow-invalid-cert', {
    describe: 'Disable certificate checks for your local HTTPS server (ignore cert/key/ca options)',
    type: 'boolean',
  })
  .options('o', {
    alias: 'open',
    describe: 'Opens the tunnel URL in your browser',
    type: 'boolean',
  })
  .option('print-requests', {
    describe: 'Print basic request info',
    type: 'boolean',
  })
  .boolean('local-https')
  .boolean('allow-invalid-cert')
  .boolean('print-requests')
  .help('help', 'Show this help and exit')
  .version(version)
  .parseSync() as unknown as CliOptions;

if (typeof argv.port !== 'number') {
  yargs.showHelp();
  console.error('\nInvalid argument: `port` must be a number');
  process.exit(1);
}

(async () => {
  try {
    const tunnel = await localtunnel({
      port: argv.port,
      host: argv.host,
      subdomain: argv.subdomain,
      local_host: argv.localHost,
      local_https: argv.localHttps,
      local_cert: argv.localCert,
      local_key: argv.localKey,
      local_ca: argv.localCa,
      allow_invalid_cert: argv.allowInvalidCert,
    });

    tunnel.on('error', err => {
      throw err;
    });

    console.log('your url is: %s', tunnel.url);

    /**
     * `cachedUrl` is set when using a proxy server that support resource caching.
     * This URL generally remains available after the tunnel itself has closed.
     * @see https://github.com/localtunnel/localtunnel/pull/319#discussion_r319846289
     */
    if (tunnel.cachedUrl) {
      console.log('your cachedUrl is: %s', tunnel.cachedUrl);
    }

    if (argv.open) {
      openurl.open(tunnel.url!);
    }

    if (argv['print-requests']) {
      tunnel.on('request', info => {
        console.log(new Date().toString(), info.method, info.path);
      });
    }
  } catch (err) {
    console.error('Error occurred:', err);
    process.exit(1);
  }
})(); 