import { useState } from 'react';
import {
  parseSecretValue,
  serializeSecretValue,
  type SecretFieldValue,
} from '../../api';

interface SecretInputProps {
  /**
   * Current stored value (as fetched from `/api/config`). May be the
   * masked sentinel `'********'`, an `${ENV_REF}` pattern, a literal
   * plaintext (rare), or empty. The component parses it on the fly so
   * the parent form can keep using `config.llm.workers[i].apiKey` as a
   * plain string.
   */
  rawValue: string | null | undefined;
  /**
   * Called when the user changes the stored form. Receives the
   * already-serialized string the parent should write back into the
   * draft config. Phase 1 keeps this string-shaped for backwards
   * compatibility with the existing `apiKey: string` config field.
   */
  onChange: (serialized: string) => void;
  placeholder?: string;
}

/**
 * 4-state secret editor (Phase 1).
 *
 * The control surface exposes three actions:
 *   - Edit literal:   user types a plaintext secret
 *   - Use env ref:    user types an env var name; saved as `${NAME}`
 *   - Clear:          erases the stored secret (saved as empty string)
 * The fourth state — `unchanged` — is what the component reports when
 * the displayed value is still the server mask and the user has not
 * touched anything.
 *
 * The form payload is currently a plain string so the existing server-
 * side mask preservation (see `src/config-manager.ts`) continues to
 * work without API changes. The 4-state contract lives in the UI today;
 * Phase 2 will lift it onto the wire.
 */
export function SecretInput({ rawValue, onChange, placeholder }: SecretInputProps) {
  const initial = parseSecretValue(rawValue);
  // Local UI state for the editor mode. Initialized from the stored
  // value so reopening the form shows the right shape.
  const [mode, setMode] = useState<SecretFieldValue['type']>(initial.type);
  // For literal / env_ref modes we keep a local draft so the user can
  // type freely. We push to the parent on each keystroke.
  const [literalDraft, setLiteralDraft] = useState(
    initial.type === 'literal' ? initial.value : '',
  );
  const [envDraft, setEnvDraft] = useState(
    initial.type === 'env_ref' ? initial.env_name : '',
  );

  const emit = (next: SecretFieldValue) => {
    onChange(serializeSecretValue(next));
  };

  const setLiteralMode = () => {
    setMode('literal');
    // Don't emit yet — wait for the user to type. Pre-fill the parent
    // with an empty literal so save reflects "literal=empty" rather than
    // the previous masked value.
    emit({ type: 'literal', value: literalDraft });
  };

  const setEnvMode = () => {
    setMode('env_ref');
    emit({ type: 'env_ref', env_name: envDraft });
  };

  const setClearedMode = () => {
    setMode('cleared');
    emit({ type: 'cleared' });
  };

  const setUnchangedMode = () => {
    setMode('unchanged');
    emit({ type: 'unchanged' });
  };

  return (
    <div className="space-y-1.5">
      {mode === 'unchanged' && (
        <div className="flex items-center gap-2">
          <input
            type="password"
            value="••••••••"
            readOnly
            className="flex-1 h-8 px-2.5 text-[13px] border border-hairline rounded-md bg-slate-50 text-slate-500"
          />
          <span className="inline-flex items-center px-2 h-6 text-2xs rounded bg-slate-100 text-slate-600">
            masked
          </span>
        </div>
      )}

      {mode === 'literal' && (
        <input
          type="password"
          value={literalDraft}
          onChange={e => {
            setLiteralDraft(e.target.value);
            emit({ type: 'literal', value: e.target.value });
          }}
          placeholder={placeholder ?? 'sk-...'}
          className="w-full h-8 px-2.5 text-[13px] border border-hairline rounded-md focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none bg-canvas"
        />
      )}

      {mode === 'env_ref' && (
        <div className="flex items-center gap-2">
          <span className="inline-flex items-center px-2 h-8 text-2xs rounded bg-slate-100 text-slate-600 font-mono">
            ${'{'}
          </span>
          <input
            type="text"
            value={envDraft}
            onChange={e => {
              const next = e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g, '');
              setEnvDraft(next);
              emit({ type: 'env_ref', env_name: next });
            }}
            placeholder="ENV_VAR_NAME"
            className="flex-1 h-8 px-2.5 text-[13px] border border-hairline rounded-md focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none bg-canvas font-mono"
          />
          <span className="inline-flex items-center px-2 h-8 text-2xs rounded bg-slate-100 text-slate-600 font-mono">
            {'}'}
          </span>
        </div>
      )}

      {mode === 'cleared' && (
        <div className="flex items-center gap-2">
          <input
            type="text"
            value="(cleared)"
            readOnly
            className="flex-1 h-8 px-2.5 text-[13px] border border-hairline rounded-md bg-slate-50 text-slate-400 italic"
          />
          <span className="inline-flex items-center px-2 h-6 text-2xs rounded bg-amber-50 dark:bg-amber-500/15 text-amber-700 dark:text-amber-300 border border-amber-200 dark:border-amber-500/30">
            will be cleared
          </span>
        </div>
      )}

      <div className="flex flex-wrap gap-1 text-2xs">
        {/* Show "Keep" only when the server actually has a masked value
            to keep; otherwise the option is meaningless. */}
        {initial.type === 'unchanged' && mode !== 'unchanged' && (
          <button
            type="button"
            onClick={setUnchangedMode}
            className="px-2 py-0.5 rounded border border-slate-200 text-slate-600 hover:bg-slate-50"
          >
            Keep current
          </button>
        )}
        {mode !== 'literal' && (
          <button
            type="button"
            onClick={setLiteralMode}
            className="px-2 py-0.5 rounded border border-slate-200 text-slate-600 hover:bg-slate-50"
          >
            Edit literal
          </button>
        )}
        {mode !== 'env_ref' && (
          <button
            type="button"
            onClick={setEnvMode}
            className="px-2 py-0.5 rounded border border-slate-200 text-slate-600 hover:bg-slate-50"
          >
            Use env var
          </button>
        )}
        {mode !== 'cleared' && (
          <button
            type="button"
            onClick={setClearedMode}
            className="px-2 py-0.5 rounded border border-amber-200 text-amber-700 dark:text-amber-300 hover:bg-amber-50 dark:hover:bg-amber-500/15"
          >
            Clear
          </button>
        )}
      </div>
    </div>
  );
}
