// {{ display_name }} MCP server — generated by mcpify. Do not hand-edit.
//
// Interactive setup wizard (REQ-1.6): collects the API URL and the
// credentials the discovered auth scheme(s) need, then persists them per
// the operator's choice: a .env file, a config.json file, or a
// ready-to-run CLI invocation printed to stdout (nothing written to disk).

import { writeFileSync } from 'node:fs';
import { join } from 'node:path';

import axios from 'axios';
import inquirer from 'inquirer';

import { headerLocationFor } from '../auth/auth-manager.js';
import type { ApiVersion, AuthMethod, Config } from '../core/config-schema.js';
import { saveCredential } from '../core/credential-storage.js';

function toEnvKey(key: string): string {
  return key.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
}

async function promptBaseUrl(): Promise<string> {
  const { url } = await inquirer.prompt<{ url: string }>([
    { type: 'input', name: 'url', message: '{{ display_name }} base URL:' },
  ]);
  try {
    await axios.head(url, { timeout: 5000 });
    console.log('reachable');
  } catch {
    console.warn('could not reach that URL yet — continuing anyway (fix it later with `test-connection`)');
  }
  return url;
}

async function promptAuthMethod(): Promise<AuthMethod> {
{%- if auth_method_keys | length == 1 %}
  return '{{ auth_method_keys.0 }}';
{%- else %}
  const { authMethod } = await inquirer.prompt<{ authMethod: AuthMethod }>([
    {
      type: 'list',
      name: 'authMethod',
      message: 'Authentication method:',
      choices: [
  {%- for key in auth_method_keys %}
        '{{ key }}',
  {%- endfor %}
      ],
    },
  ]);
  return authMethod;
{%- endif %}
}

async function promptTransport(): Promise<Config['transport']> {
  const { transport } = await inquirer.prompt<{ transport: Config['transport'] }>([
    {
      type: 'list',
      name: 'transport',
      message: 'Which transport will this deployment use?',
      choices: [
        { name: 'stdio (spawned as a subprocess by the MCP client)', value: 'stdio' },
        { name: 'http (a standalone server the MCP client connects to over the network)', value: 'http' },
      ],
    },
  ]);
  return transport;
}

// mcpify:versions:begin
async function promptApiVersion(): Promise<ApiVersion> {
{%- if version_entries | length == 1 %}
  return '{{ version_entries.0.label }}';
{%- else %}
  const { apiVersion } = await inquirer.prompt<{ apiVersion: ApiVersion }>([
    {
      type: 'list',
      name: 'apiVersion',
      message: 'API version to use:',
      default: '{{ default_version_label }}',
      choices: [
  {%- for v in version_entries %}
        { name: '{{ v.label }}{% if v.label == default_version_label %} (default/latest){% endif %}', value: '{{ v.label }}' },
  {%- endfor %}
      ],
    },
  ]);
  return apiVersion;
{%- endif %}
}
// mcpify:versions:end

async function promptCredentials(authMethod: AuthMethod): Promise<Record<string, string>> {
  switch (authMethod) {
{%- if "basic" in auth_method_keys %}
    case 'basic':
      return inquirer.prompt([
        { type: 'input', name: 'username', message: 'Username:' },
        { type: 'password', name: 'password', message: 'Password:' },
      ]);
{%- endif %}
{%- if "pat" in auth_method_keys %}
    case 'pat':
      return inquirer.prompt([{ type: 'password', name: 'token', message: 'Personal access token:' }]);
{%- endif %}
{%- if "apiKey" in auth_method_keys %}
    case 'apiKey':
      return inquirer.prompt([{ type: 'password', name: 'apiKey', message: 'API key:' }]);
{%- endif %}
{%- if "oauth2" in auth_method_keys %}
    case 'oauth2':
      return inquirer.prompt([
        { type: 'input', name: 'clientId', message: 'OAuth2 client ID:' },
        { type: 'password', name: 'clientSecret', message: 'OAuth2 client secret (leave blank if none):' },
        { type: 'input', name: 'tokenUrl', message: 'OAuth2 token URL:' },
        {
          type: 'password',
          name: 'accessToken',
          message: 'Existing access token, if you already have one (leave blank to skip):',
        },
      ]);
{%- endif %}
{%- if "oauth1" in auth_method_keys %}
    case 'oauth1':
      return inquirer.prompt([
        { type: 'input', name: 'consumerKey', message: 'OAuth1 consumer key:' },
        { type: 'input', name: 'privateKeyPath', message: 'Path to RSA private key file:' },
      ]);
{%- endif %}
    default:
      return {};
  }
}

async function promptPersistence(env: Record<string, string>): Promise<void> {
  const { method } = await inquirer.prompt<{ method: 'env' | 'json' | 'print' }>([
    {
      type: 'list',
      name: 'method',
      message: 'How should these settings be saved?',
      choices: [
        { name: 'Write a .env file', value: 'env' },
        { name: 'Write a config.json file', value: 'json' },
        { name: 'Print a ready-to-run CLI invocation (nothing written to disk)', value: 'print' },
      ],
    },
  ]);

  if (method === 'env') {
    const contents = Object.entries(env)
      .map(([key, value]) => `${key}=${value}`)
      .join('\n');
    writeFileSync(join(process.cwd(), '.env'), `${contents}\n`);
    console.log('Wrote .env');
  } else if (method === 'json') {
    writeFileSync(join(process.cwd(), 'config.json'), JSON.stringify(env, null, 2));
    console.log('Wrote config.json');
  } else {
    const flags = Object.entries(env)
      .map(([key, value]) => `--${key.toLowerCase().replace(/_/g, '-')} ${JSON.stringify(value)}`)
      .join(' ');
    console.log(`{{ project_name }} start ${flags}`);
  }
}

/**
 * Prints a ready-to-use MCP client config (the `mcpServers` block a host
 * like Claude Code/Desktop expects) for whichever transport was selected
 * — the stdio and http shapes are mutually exclusive, never both, since
 * they're two different ways of running this same server and a client
 * only ever picks one. HTTP transport shows credentials as headers only
 * (never env/CLI args, matching `AuthManager.applyAuthHeaders`'s
 * HTTP-only-uses-per-request-credentials behavior); stdio shows both the
 * `env` block and the equivalent all-CLI-args invocation, since the
 * config cascade accepts either for a spawned subprocess.
 */
function printMcpClientConfig(transport: Config['transport'], authMethod: AuthMethod, env: Record<string, string>): void {
  if (transport === 'stdio') {
    const config = {
      mcpServers: {
        ['{{ project_name }}']: {
          command: '{{ project_name }}',
          args: ['start'],
          env,
        },
      },
    };
    console.log('\nMCP client config (stdio):');
    console.log(JSON.stringify(config, null, 2));
    const cliArgs = Object.entries(env)
      .map(([key, value]) => `--${key.toLowerCase().replace(/_/g, '-')} ${JSON.stringify(value)}`)
      .join(' ');
    console.log(`(equivalently: \`{{ project_name }} start ${cliArgs}\`)`);
    return;
  }

{%- if "oauth1" in auth_method_keys %}
  if (authMethod === 'oauth1') {
    console.log(
      "\nOAuth1 is not supported over HTTP transport: its signature must be recomputed per " +
        "request against the destination URL using the server's consumer key/secret, which a " +
        'simple incoming-header relay cannot provide. Use stdio transport for this API instead.',
    );
    return;
  }
{%- endif %}
  const [, headerName] = headerLocationFor(authMethod);
  const config = {
    mcpServers: {
      ['{{ project_name }}']: {
        url: 'http://127.0.0.1:3000/mcp',
        headers: { [headerName]: '<credential value here>' },
      },
    },
  };
  console.log('\nMCP client config (http) — adjust the host/port to match how you run `{{ project_name }} http`:');
  console.log(JSON.stringify(config, null, 2));
  console.log(
    `Credentials are never read from local config/env over HTTP transport — every request must carry its own "${headerName}" header.`,
  );
}

export async function runSetupWizard(): Promise<void> {
  const url = await promptBaseUrl();
  const authMethod = await promptAuthMethod();
  const credentials = await promptCredentials(authMethod);
  const apiVersion = await promptApiVersion();
  const transport = await promptTransport();

  await saveCredential('active-credentials', JSON.stringify(credentials));

  const env: Record<string, string> = {
    ['{{ tool_prefix_env }}_URL']: url,
    ['{{ tool_prefix_env }}_AUTH_METHOD']: authMethod,
    ['{{ tool_prefix_env }}_API_VERSION']: apiVersion,
    ['{{ tool_prefix_env }}_TRANSPORT']: transport,
  };
  for (const [key, value] of Object.entries(credentials)) {
    env[`{{ tool_prefix_env }}_${toEnvKey(key)}`] = value;
  }

  await promptPersistence(env);
  printMcpClientConfig(transport, authMethod, env);

  const runCommand = transport === 'stdio' ? 'start' : 'http';
  console.log(`Setup complete! Run: {{ project_name }} ${runCommand}`);
}
