import { useState } from 'react';
import { useTranslation } from 'react-i18next';

interface Props {
  taskId: number;
  className?: string;
}

type Status =
  | { kind: 'idle' }
  | { kind: 'loading' }
  | { kind: 'success'; recordingName: string }
  | { kind: 'error'; message: string }
  | { kind: 'no_recording' };

/**
 * Small toolbar button that flushes the active noVNC recording buffer to
 * disk via POST /api/users/me/recordings/flush?taskId=<taskId>.
 * Shows an inline confirmation with the saved file name for 4 s on success,
 * or a plain-text error for 5 s on failure.
 */
export function SaveRecordingButton({ taskId, className }: Props) {
  const { t } = useTranslation('browser');
  const [status, setStatus] = useState<Status>({ kind: 'idle' });
  const [linkVisible, setLinkVisible] = useState(false);

  const baseClass =
    'text-2xs px-2 py-1 rounded-md border border-hairline bg-canvas hover:bg-surface text-slate-700 disabled:opacity-50';
  const merged = className ? `${baseClass} ${className}` : baseClass;

  async function handleClick() {
    setStatus({ kind: 'loading' });
    setLinkVisible(false);

    try {
      const res = await fetch(
        `/api/users/me/recordings/flush?taskId=${encodeURIComponent(taskId)}`,
        { method: 'POST', credentials: 'include' },
      );

      if (res.status === 404) {
        setStatus({ kind: 'no_recording' });
        setTimeout(() => setStatus({ kind: 'idle' }), 5000);
        return;
      }

      if (!res.ok) {
        let msg = `HTTP ${res.status}`;
        try {
          const body = await res.json() as { message?: string; error?: string };
          msg = body.message ?? body.error ?? msg;
        } catch {
          // ignore parse errors
        }
        setStatus({ kind: 'error', message: msg });
        setTimeout(() => setStatus({ kind: 'idle' }), 5000);
        return;
      }

      const body = await res.json() as { ok: boolean; recordingName?: string };
      const recordingName = body.recordingName ?? 'recording';
      setStatus({ kind: 'success', recordingName });
      setLinkVisible(true);
      setTimeout(() => setStatus({ kind: 'idle' }), 4000);
      setTimeout(() => setLinkVisible(false), 10000);
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      setStatus({ kind: 'error', message: msg });
      setTimeout(() => setStatus({ kind: 'idle' }), 5000);
    }
  }

  function handleUserFolderClick() {
    const url = new URL(window.location.href);
    url.searchParams.set('page', 'userfolder');
    window.location.search = url.searchParams.toString();
  }

  function label(): string {
    switch (status.kind) {
      case 'loading':
        return t('saveRecording.saving');
      case 'success':
        return t('saveRecording.saved', { name: status.recordingName });
      case 'error':
        return t('saveRecording.error', { message: status.message });
      case 'no_recording':
        return t('saveRecording.noRecording');
      default:
        return t('saveRecording.save');
    }
  }

  return (
    <span className="inline-flex flex-col items-start gap-1">
      <button
        type="button"
        onClick={() => void handleClick()}
        disabled={status.kind === 'loading'}
        className={merged}
        title={
          status.kind === 'no_recording'
            ? t('saveRecording.noRecordingTitle')
            : t('saveRecording.saveTitle')
        }
      >
        {label()}
      </button>
      {linkVisible && status.kind === 'success' && (
        <button
          type="button"
          onClick={handleUserFolderClick}
          className="text-[10px] text-accent hover:underline pl-0.5"
        >
          {t('saveRecording.openInUserFolder')}
        </button>
      )}
    </span>
  );
}
