import { useState } from 'react';
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 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?.(`Rotation job 開始: ${resp.jobId}`, 'success');
      setShowStartDialog(false);
    },
    onError: (e) => {
      showToast?.(e instanceof Error ? e.message : 'Rotation 開始失敗', 'error');
    },
  });

  const status = statusQuery.data;

  return (
    <div className="space-y-3">
      <div>
        <h3 className="text-sm font-semibold text-slate-900">Master Key Rotation</h3>
        <p className="text-2xs text-slate-500 mt-1 leading-relaxed">
          <code className="font-mono">MCP_ENCRYPTION_KEY</code> をローテーションします。実行中は SSH 書き込み系
          API が 503 を返し、UI からは保存・更新が一時停止します (読み取りは可能)。
          {' '}<strong>v1 ではメンテナンスフラグの設定のみ。実際の DEK 再ラップは未実装。</strong>
        </p>
      </div>

      <div className="rounded-md border border-hairline bg-white 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">現在の状態</div>
            <div className="text-xs text-slate-800 mt-0.5">
              {activeJobId === null && <span>idle (rotation 未実行)</span>}
              {activeJobId !== null && statusQuery.isLoading && <span className="text-slate-400">確認中…</span>}
              {activeJobId !== null && status === null && (
                <span className="text-emerald-700">job {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 text-amber-700">
                      stub (v1)
                    </span>
                  )}
                </>
              )}
            </div>
            {status?.startedAt && (
              <div className="text-2xs text-slate-500 mt-0.5">開始: {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"
          >
            Rotation を開始
          </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 [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-white rounded-md shadow-lg border border-amber-300 overflow-hidden">
        <div className="px-4 py-3 border-b border-amber-200 bg-amber-50">
          <h3 className="text-sm font-semibold text-amber-900">⚠️ Master Key Rotation を開始</h3>
        </div>
        <div className="px-4 py-3 space-y-3">
          <p className="text-xs text-slate-700 leading-relaxed">
            この操作は<strong>メンテナンスモードを有効化</strong>します。
            SSH 接続の作成・更新・削除・テストが一時的にすべて 503 を返します。
            <br />
            ⚠️ v1 では DEK 再ラップは未実装です。 メンテナンスを解除するには手動でフラグをクリアする必要があります。
          </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="MCP_ENCRYPTION_KEY を新しい値に置き換えるため"
              autoFocus
            />
          </label>
          <label className="block">
            <div className="text-2xs font-semibold text-slate-500 uppercase tracking-wide mb-1">
              確認のため <code className="font-mono">ROTATE</code> と入力してください
            </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">
            キャンセル
          </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 ? '開始中…' : 'Rotation を開始'}
          </button>
        </div>
      </div>
    </div>
  );
}
