import { i18n } from '../i18n'
import { sdk } from '../sdk'
import { DATA_MOUNT_PATH, IMAGE_ID } from '../utils'

/**
 * "Set Anthropic API Key (Architect)" action.
 *
 * The Architect agent (Phase-1 thesis generation) runs on Claude. The container
 * entrypoint (docker_entrypoint.sh) loads the key ONCE at boot from
 *   /data/secrets/anthropic-api-key
 * and exports it as ANTHROPIC_API_KEY into the long-running server process.
 *
 * This action lets a non-technical operator paste the key into a masked field
 * straight from the StartOS UI — no SSH/terminal — and writes it to that file
 * with owner-only (0600) permissions. The key never leaves the box.
 *
 * Two deliberate properties:
 *   - The secret is piped to the writer over STDIN (never argv/env), so it can't
 *     surface in a process listing. We strip stray CR/LF a paste may carry —
 *     exactly what the entrypoint already does when it reads the file back.
 *   - A service RESTART is REQUIRED for the change to take effect: the entrypoint
 *     reads the file only at startup, so the running server won't see a newly
 *     saved key until it is restarted. Both the metadata `warning` and the
 *     success `message` say so.
 *
 * Like the ingest actions, this runs in its OWN subcontainer with the main
 * /data volume mounted read-write; it does NOT go through docker_entrypoint.sh.
 */

const { InputSpec, Value } = sdk

const KEY_FILE = `${DATA_MOUNT_PATH}/secrets/anthropic-api-key`

// Single shell command: ensure /data/secrets exists + locked (700), write the
// key from stdin stripped of CR/LF, then 0600 the file. umask 077 makes the
// created file owner-only even before the explicit chmod. The `tr -d '\n\r'`
// mirrors how docker_entrypoint.sh reads the key back.
const WRITE_KEY_SCRIPT =
  'set -eu; umask 077; ' +
  'mkdir -p "$DATA_DIR/secrets"; chmod 700 "$DATA_DIR/secrets"; ' +
  "tr -d '\\n\\r' > \"$DATA_DIR/secrets/anthropic-api-key\"; " +
  'chmod 600 "$DATA_DIR/secrets/anthropic-api-key"'

export const inputSpec = InputSpec.of({
  apiKey: Value.text({
    name: i18n('Anthropic API Key'),
    description: i18n(
      'Your Anthropic (Claude) API key. It is written to ' +
        '/data/secrets/anthropic-api-key on this server (owner-only, 0600) and ' +
        'never leaves the box. Required for the Architect thesis-generation ' +
        'features. Leave blank to keep the current key unchanged.',
    ),
    warning: null,
    required: true,
    default: null,
    // Camouflage the input with dots so the key is not shown on screen.
    masked: true,
    placeholder: 'sk-ant-...',
  }),
})

export const setAnthropicApiKey = sdk.Action.withInput(
  // id
  'set-anthropic-api-key',

  // metadata
  async ({ effects }) => ({
    name: i18n('Set Anthropic API Key (Architect)'),
    description: i18n(
      'Paste your Anthropic (Claude) API key to enable the Architect ' +
        'thesis-generation features. The key is stored only on this server at ' +
        '/data/secrets/anthropic-api-key with owner-only (0600) permissions and ' +
        'is never sent anywhere except the Anthropic API at generation time. ' +
        'Restart the service after saving for the key to take effect.',
    ),
    warning: i18n(
      'After saving, restart Ten31 Database (Stop, then Start) so the new key is ' +
        'loaded. The running service does not pick up the key until it restarts.',
    ),
    allowedStatuses: 'any',
    group: null,
    visibility: 'enabled',
  }),

  // form input specification
  inputSpec,

  // pre-fill: never read the secret back out — always present a blank field.
  async ({ effects, prefill }) => null,

  // execution
  async ({ effects, input }) => {
    const subcontainer = await sdk.SubContainer.of(
      effects,
      { imageId: IMAGE_ID },
      sdk.Mounts.of().mountVolume({
        volumeId: 'main',
        subpath: null,
        mountpoint: DATA_MOUNT_PATH,
        readonly: false,
      }),
      'ten31-database-set-anthropic-api-key',
    )

    try {
      // The key is piped in over stdin (options.input) — never argv/env — so it
      // cannot appear in a process listing.
      await subcontainer.execFail(
        ['/bin/sh', '-c', WRITE_KEY_SCRIPT],
        { env: { DATA_DIR: DATA_MOUNT_PATH }, input: input.apiKey },
        60 * 1000,
      )
    } finally {
      await subcontainer.destroy()
    }

    return {
      version: '1',
      title: i18n('Anthropic API key saved'),
      message: i18n(
        `Your Anthropic API key was written to ${KEY_FILE} (permissions 0600). ` +
          'IMPORTANT: restart Ten31 Database now (Stop, then Start) so the ' +
          'Architect picks up the new key, then open the Thesis Workshop to ' +
          'generate.',
      ),
      result: null,
    }
  },
)
