import { FC, useEffect, useState } from 'react';
import { FaCheck, FaCopy, FaKey, FaTimes } from 'react-icons/fa';
import { LocalizeText } from '../../api';
import { useHousekeepingStore } from '../../hooks';
const COPY_CONFIRM_MS = 1600;
/**
* Password-reveal card — surfaces the plaintext password the emulator
* returned from `HousekeepingResetUserPasswordEvent` so the operator
* can read it once and copy it out-of-band to the user.
*
* Sensitive data, so:
* - Renders OUTSIDE the auto-dismissing status banner (which truncates
* long content and disappears after 4s).
* - Stays put until the operator explicitly dismisses — they have to
* acknowledge they've copied/communicated the secret.
* - The plaintext lives in `useHousekeepingStore.passwordReveal` and
* never flows through the generic success-toast / banner pipeline
* (`useHousekeepingActions.resetUserPassword` intercepts it before
* `wrap`'s default path).
* - The clipboard write uses the modern `navigator.clipboard.writeText`
* when available, with a `document.execCommand('copy')` fallback for
* non-secure-context legacy paths so the button still works inside an
* `http://` deployment.
*/
export const HousekeepingPasswordReveal: FC = () =>
{
const { passwordReveal, clearPasswordReveal } = useHousekeepingStore();
const [ copyState, setCopyState ] = useState<'idle' | 'ok' | 'fail'>('idle');
// Reset the "copied!" visual whenever a new reveal lands so the
// operator doesn't see a stale checkmark from a previous reset.
useEffect(() =>
{
setCopyState('idle');
}, [ passwordReveal?.password ]);
// Auto-revert the copy-confirmation icon back to the copy icon
// a short while after a successful copy. The plaintext itself
// stays revealed until the operator explicitly dismisses.
useEffect(() =>
{
if(copyState === 'idle') return;
const handle = window.setTimeout(() => setCopyState('idle'), COPY_CONFIRM_MS);
return () => window.clearTimeout(handle);
}, [ copyState ]);
if(!passwordReveal) return null;
const copyPassword = async () =>
{
const text = passwordReveal.password;
if(!text) return;
// Modern path — requires a secure context (https / wss / localhost).
if(typeof navigator !== 'undefined' && navigator.clipboard && window.isSecureContext)
{
try
{
await navigator.clipboard.writeText(text);
setCopyState('ok');
return;
}
catch
{
// Fall through to the legacy path below — some browsers
// still gate the modern API behind extra permissions even
// in secure contexts.
}
}
// Legacy fallback: stage a textarea, select, exec copy. Works
// on plain-http deployments where `navigator.clipboard` is
// refused. The textarea is positioned off-screen so the user
// doesn't see a flash.
try
{
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.setAttribute('readonly', '');
textarea.style.position = 'absolute';
textarea.style.left = '-9999px';
textarea.style.top = '0';
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, text.length);
const ok = document.execCommand('copy');
document.body.removeChild(textarea);
setCopyState(ok ? 'ok' : 'fail');
}
catch
{
setCopyState('fail');
}
};
const copyIcon = copyState === 'ok' ?
{ LocalizeText('housekeeping.password.hint') }