import { z } from 'zod';

export type SettingType =
  | 'string'
  | 'password'
  | 'number'
  | 'boolean'
  | 'select'
  | 'radio'
  | 'url'
  | 'email'
  | 'textarea'
  /**
   * Renders a dropdown of the current port's CRM users (email + name).
   * Stored as the user's UUID. Used for fields that bind a CRM user to a
   * Documenso recipient slot for in-CRM notification routing.
   */
  | 'user-select';

export type SettingScope = 'port' | 'global';

export type SettingSource = 'port' | 'global' | 'env' | 'default';

export interface SettingOption {
  value: string;
  label: string;
}

export interface SettingEntry {
  /** Stable key written to system_settings.key. Use snake_case. */
  key: string;
  /** Grouping name used by the admin form generator (e.g. "documenso.api"). */
  section: string;
  /** UI label. */
  label: string;
  /** UI description (plain text - can include backticks for inline code). */
  description: string;
  /** Drives both validation and form input rendering. */
  type: SettingType;
  /** select-only - list of option choices. */
  options?: SettingOption[];
  /** Optional Zod schema. When omitted, a type-appropriate default is used. */
  validator?: z.ZodTypeAny;
  /** Default applied when port + global + env all absent. */
  defaultValue?: string | number | boolean | null;
  /** Encrypt at rest with AES-256-GCM. Implies sensitive. */
  encrypted?: boolean;
  /** Per-port (with global + env fallback) or global-only (super-admin). */
  scope: SettingScope;
  /** Env var name consulted when port + global blank. */
  envFallback?: string;
  /** Value transformer applied after resolution (e.g. coerce string→number). */
  transform?: (raw: unknown) => unknown;
  /**
   * Sensitive: never surface cleartext via admin API. Encrypted fields are
   * sensitive by default; non-encrypted fields may still be marked sensitive
   * (e.g. an externally-shared secret) - the API emits `<key>IsSet: boolean`.
   */
  sensitive?: boolean;
  /** Placeholder text shown in the input. */
  placeholder?: string;
}

/**
 * Resolved-value response shape returned to the admin UI.
 *
 * - `source` tells the UI whether the value came from the port row, the
 *   global row, the env fallback, or the registry default - which drives
 *   the "Using env fallback" badge.
 * - `value` carries the resolved cleartext for non-sensitive fields. For
 *   sensitive / encrypted fields it is omitted and only `isSet` is exposed.
 */
export interface ResolvedSetting<T = unknown> {
  key: string;
  source: SettingSource;
  isSet: boolean;
  value?: T;
}
