import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

interface RotationStub {
  jobId: string;
  status: string;
  startedAt?: string;
  progress?: { note: string };
  notImplemented?: boolean;
}

interface StartResponse {
  jobId: string;
  status: string;
  detail: string;
  notImplemented?: boolean;
}

/**
 * Probe the rotation status by reading the maintenance flag indirectly.
 *
 * The /rotate-master-key/:jobId endpoint returns 404 when no job is active.
 * For v1 there's no "list all jobs" endpoint; we just track the latest jobId
 * locally and re-fetch its status.
 */
async function fetchJobStatus(jobId: string): Promise<RotationStub | null> {
  const res = await fetch(`/api/ssh/admin/rotate-master-key/${encodeURIComponent(jobId)}`, { credentials: 'include' });
  if (res.status === 404) return null;
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return (await res.json()) as RotationStub;
}

async function startRotation(reason: string): Promise<StartResponse> {
  const res = await fetch('/api/ssh/admin/rotate-master-key', {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ reason }),
  });
  if (!res.ok) {
    let detail = `HTTP ${res.status}`;
    try {
      const j = await res.json();
      if (j?.error) detail = j.detail ? `${j.error}: ${typeof j.detail === 'string' ? j.detail : JSON.stringify(j.detail)}` : j.error;
    } catch { /* ignore */ }
    throw new Error(detail);
  }
  return (await res.json()) as StartResponse;
}

interface Props {
  showToast?: (msg: string, variant?: 'success' | 'error') => void;
}

export function SshMasterKeyRotationForm({ showToast }: Props) {
  const { t } = useTranslation('settings');
  const qc = useQueryClient();
  const [activeJobId, setActiveJobId] = useState<string | null>(null);
  const [showStartDialog, setShowStartDialog] = useState(false);

  // Poll status every 3s while a job is known.
  const statusQuery = useQuery({
    queryKey: ['ssh', 'admin', 'rotation', activeJobId],
    queryFn: () => activeJobId ? fetchJobStatus(activeJobId) : Promise.resolve(null),
    refetchInterval: activeJobId ? 3000 : false,
    enabled: activeJobId !== null,
  });

  const startMutation = useMutation({
    mutationFn: startRotation,
    onSuccess: (resp) => {
      setActiveJobId(resp.jobId);
      qc.invalidateQueries({ queryKey: ['ssh', 'admin', 'rotation'] });
      showToast?.(t('ssh.rotation.toast.started', { jobId: resp.jobId }), 'success');
      setShowStartDialog(false);
    },
    onError: (e) => {
      showToast?.(e instanceof Error ? e.message : t('ssh.rotation.toast.startFailed'), 'error');
    },
  });

  const status = statusQuery.data;

  return (
    <div className="space-y-3">
      <div>
        <h3 className="text-sm font-semibold text-slate-900">{t('ssh.rotation.title')}</h3>
        <p className="text-2xs text-slate-500 mt-1 leading-relaxed">
          {t('ssh.rotation.desc')}
        </p>
      </div>

      <div className="rounded-md border border-hairline bg-canvas p-3">
        <div className="flex items-center justify-between gap-3">
          <div className="min-w-0">
            <div className="text-2xs font-semibold text-slate-500 uppercase tracking-wide">{t('ssh.rotation.currentState')}</div>
            <div className="text-xs text-slate-800 mt-0.5">
              {activeJobId === null && <span>{t('ssh.rotation.idle')}</span>}
              {activeJobId !== null && statusQuery.isLoading && <span className="text-slate-400">{t('ssh.rotation.checking')}</span>}
              {activeJobId !== null && status === null && (
                <span className="text-emerald-700 dark:text-emerald-300">{t('ssh.rotation.jobDoneOrCleared', { jobId: activeJobId })}</span>
              )}
              {status && (
                <>
                  <span className="font-mono">{status.status}</span>
                  {status.notImplemented && (
                    <span className="ml-2 inline-block px-1.5 py-0.5 rounded text-[10px] font-medium bg-amber-50 dark:bg-amber-500/15 text-amber-700 dark:text-amber-300">
                      stub (v1)
                    </span>
                  )}
                </>
              )}
            </div>
            {status?.startedAt && (
              <div className="text-2xs text-slate-500 mt-0.5">{t('ssh.rotation.startedAt', { ts: status.startedAt })}</div>
            )}
            {status?.progress?.note && (
              <div className="text-2xs text-slate-500 mt-0.5">{status.progress.note}</div>
            )}
          </div>
          <button
            type="button"
            onClick={() => setShowStartDialog(true)}
            disabled={status !== null && status !== undefined}
            className="px-3 h-7 text-xs font-semibold bg-amber-600 text-white rounded-md hover:bg-amber-700 disabled:opacity-50 flex-shrink-0"
          >
            {t('ssh.rotation.startButton')}
          </button>
        </div>
      </div>

      {showStartDialog && (
        <ConfirmDialog
          submitting={startMutation.isPending}
          onCancel={() => setShowStartDialog(false)}
          onSubmit={async (reason) => { await startMutation.mutateAsync(reason); }}
        />
      )}
    </div>
  );
}

function ConfirmDialog({
  submitting,
  onCancel,
  onSubmit,
}: {
  submitting: boolean;
  onCancel: () => void;
  onSubmit: (reason: string) => Promise<void>;
}) {
  const { t } = useTranslation('settings');
  const [reason, setReason] = useState('');
  const [typed, setTyped] = useState('');
  const [error, setError] = useState<string | null>(null);
  const reasonValid = reason.trim().length >= 8;
  const typedOk = typed.trim().toUpperCase() === 'ROTATE';

  async function handleSubmit() {
    if (!reasonValid || !typedOk) return;
    setError(null);
    try {
      await onSubmit(reason.trim());
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
    }
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
      <div className="w-full max-w-lg bg-surface rounded-md shadow-lg border border-amber-300 overflow-hidden">
        <div className="px-4 py-3 border-b border-amber-200 dark:border-amber-500/30 bg-amber-50 dark:bg-amber-500/15">
          <h3 className="text-sm font-semibold text-amber-900 dark:text-amber-300">{t('ssh.rotation.confirmTitle')}</h3>
        </div>
        <div className="px-4 py-3 space-y-3">
          <p className="text-xs text-slate-700 leading-relaxed">
            {t('ssh.rotation.confirmBody1')}
            <br />
            {t('ssh.rotation.confirmBody2')}
          </p>
          <label className="block">
            <div className="text-2xs font-semibold text-slate-500 uppercase tracking-wide mb-1">Reason (≥ 8 chars)</div>
            <input
              type="text"
              value={reason}
              onChange={e => setReason(e.target.value)}
              className="w-full text-xs px-2 py-1.5 border border-hairline rounded"
              placeholder={t('ssh.rotation.reasonPlaceholder')}
              autoFocus
            />
          </label>
          <label className="block">
            <div className="text-2xs font-semibold text-slate-500 uppercase tracking-wide mb-1">
              {t('ssh.rotation.typeToConfirm')}
            </div>
            <input
              type="text"
              value={typed}
              onChange={e => setTyped(e.target.value)}
              className="w-full text-xs px-2 py-1.5 border border-hairline rounded font-mono"
              placeholder="ROTATE"
            />
          </label>
          {error && <div className="text-xs text-red-600">{error}</div>}
        </div>
        <div className="px-4 py-3 border-t border-hairline flex items-center justify-end gap-2 bg-surface/50">
          <button onClick={onCancel} disabled={submitting} className="px-2 h-7 text-2xs text-slate-700 border border-hairline rounded hover:bg-surface disabled:opacity-50">
            {t('ssh.common.cancel')}
          </button>
          <button
            onClick={handleSubmit}
            disabled={!reasonValid || !typedOk || submitting}
            className="px-3 h-7 text-xs font-semibold bg-amber-600 text-white rounded-md hover:bg-amber-700 disabled:opacity-50"
          >
            {submitting ? t('ssh.rotation.starting') : t('ssh.rotation.startButton')}
          </button>
        </div>
      </div>
    </div>
  );
}
