'use client';

import { useCallback, useState } from 'react';

import { useCfgAccountsApiKeyRegenerateCreate } from '../_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRegenerateCreate';
import { useCfgAccountsApiKeyRetrieve } from '../_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRetrieve';
import { useCfgAccountsApiKeyRevealCreate } from '../_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyRevealCreate';
import { useCfgAccountsApiKeyTestCreate } from '../_api/generated/_cfg_accounts/hooks/useCfgAccountsApiKeyTestCreate';

export interface ApiKeyTestResult {
  valid: boolean;
  userId: string | null;
}

export interface UseApiKeyReturn {
  /**
   * The key to display. Masked by default (from retrieve). Becomes the FULL
   * value after `reveal()` or `regenerate()` resolves, so the user can copy it.
   */
  apiKey: string | null;
  /** True once `reveal()`/`regenerate()` has surfaced the full (unmasked) key. */
  isRevealed: boolean;
  reissuedAt: string | null;
  createdAt: string | null;
  isLoading: boolean;
  isRevealing: boolean;
  isRegenerating: boolean;
  isTesting: boolean;
  /**
   * Fetch the current full key WITHOUT rotating it (the durable value every one
   * of the user's agents uses). Use this to let the user copy their key for
   * agent onboarding — `regenerate()` would invalidate the agents already using it.
   */
  reveal: () => Promise<void>;
  regenerate: () => Promise<void>;
  testKey: (key: string) => Promise<ApiKeyTestResult>;
  refresh: () => void;
}

export function useApiKey(): UseApiKeyReturn {
  const { data, isLoading, mutate } = useCfgAccountsApiKeyRetrieve();
  const { trigger: revealTrigger, isMutating: isRevealing } = useCfgAccountsApiKeyRevealCreate();
  const { trigger: regenerateTrigger, isMutating: isRegenerating } = useCfgAccountsApiKeyRegenerateCreate();
  const { trigger: testTrigger, isMutating: isTesting } = useCfgAccountsApiKeyTestCreate();

  // reveal/regenerate POST responses contain the FULL key. We store it
  // separately so the user can copy it before (or instead of) a masked refetch.
  const [freshKey, setFreshKey] = useState<string | null>(null);

  const apiKey = freshKey ?? (data?.key ?? null);
  const isRevealed = freshKey !== null;
  const reissuedAt = (data as Record<string, unknown> | undefined)?.reissued_at as string | null ?? null;
  const createdAt = (data as Record<string, unknown> | undefined)?.created_at as string | null ?? null;

  const reveal = useCallback(async () => {
    const result = await revealTrigger({} as never);
    // The reveal response has the current full key — surface it WITHOUT rotating.
    const fullKey = (result as Record<string, unknown> | undefined)?.key as string | undefined;
    if (fullKey) {
      setFreshKey(fullKey);
    }
  }, [revealTrigger]);

  const regenerate = useCallback(async () => {
    const result = await regenerateTrigger({} as never);
    // The POST response has the full key — surface it immediately.
    const newKey = (result as Record<string, unknown> | undefined)?.key as string | undefined;
    if (newKey) {
      setFreshKey(newKey);
    }
  }, [regenerateTrigger]);

  const testKey = useCallback(async (key: string): Promise<ApiKeyTestResult> => {
    const result = await testTrigger({ body: { key } } as never);
    const record = result as Record<string, unknown> | undefined;
    return {
      valid: Boolean(record?.valid),
      userId: (record?.user_id as string | null) ?? null,
    };
  }, [testTrigger]);

  const refresh = useCallback(() => {
    setFreshKey(null);
    mutate();
  }, [mutate]);

  return {
    apiKey,
    isRevealed,
    reissuedAt,
    createdAt,
    isLoading,
    isRevealing,
    isRegenerating,
    isTesting,
    reveal,
    regenerate,
    testKey,
    refresh,
  };
}
