/**
 * 🔄 Refresh Token 공통 모듈
 *
 * 프록시(/api/proxy)와 serverFetch 양쪽에서 사용하는 공통 토큰 갱신 로직
 *
 * 문제: useEffect에서 여러 API 동시 호출 시 refresh_token 충돌
 * - 첫 번째 요청이 refresh_token 사용 → 성공 (토큰 폐기됨)
 * - 두 번째 요청이 같은 refresh_token 사용 → 실패 (이미 폐기됨)
 *
 * 해결: 5초간 refresh 결과 캐싱
 * - 동시 요청들이 같은 새 토큰을 공유
 * - 진행 중인 refresh Promise도 공유하여 중복 요청 방지
 * - 프록시와 serverFetch가 같은 캐시를 공유하여 더 효율적
 */

export type RefreshResult = {
  success: boolean;
  accessToken?: string;
  refreshToken?: string;
  expiresIn?: number;
};

// 캐시 상태 (모듈 레벨에서 공유)
let refreshCache: {
  promise: Promise<RefreshResult> | null;
  timestamp: number;
  result: RefreshResult | null;
} = {
  promise: null,
  timestamp: 0,
  result: null,
};

const REFRESH_CACHE_TTL = 5000; // 5초

/**
 * 실제 토큰 갱신 수행 (내부 함수)
 */
async function doRefreshToken(refreshToken: string): Promise<RefreshResult> {
  try {
    const refreshUrl = `${process.env.NEXT_PUBLIC_API_URL}/api/v1/refresh`;
    console.log('🔄 [RefreshToken] Refresh request:', {
      url: refreshUrl,
      hasApiKey: !!process.env.API_KEY,
      refreshTokenLength: refreshToken?.length,
    });

    const response = await fetch(refreshUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'X-API-KEY': process.env.API_KEY || '',
      },
      body: JSON.stringify({
        refresh_token: refreshToken,
      }),
    });

    if (!response.ok) {
      const errorBody = await response.text();
      console.warn('🔴 [RefreshToken] Token refresh failed:', {
        status: response.status,
        statusText: response.statusText,
        body: errorBody,
      });
      return { success: false };
    }

    const data = await response.json();
    console.log('✅ [RefreshToken] Token refreshed successfully');

    return {
      success: true,
      accessToken: data.access_token,
      refreshToken: data.refresh_token,
      expiresIn: data.expires_in,
    };
  } catch (error) {
    console.error('🔴 [RefreshToken] Token refresh error:', error);
    return { success: false };
  }
}

/**
 * 토큰 갱신 함수 (5초 캐싱 적용)
 *
 * 동시 요청 시:
 * 1. 캐시된 결과가 있으면 즉시 반환
 * 2. 진행 중인 refresh가 있으면 그 Promise를 기다림
 * 3. 둘 다 없으면 새 refresh 시작
 *
 * @param refreshToken - 현재 refresh_token
 * @param caller - 호출자 식별 (로그용: 'PROXY' | 'serverFetch')
 */
export async function refreshAccessToken(
  refreshToken: string,
  caller: string = 'unknown'
): Promise<RefreshResult> {
  const now = Date.now();

  // 1. 캐시된 성공 결과가 유효하면 즉시 반환
  if (refreshCache.result && refreshCache.result.success && now - refreshCache.timestamp < REFRESH_CACHE_TTL) {
    console.log(`🔵 [${caller}] Using cached refresh result (age: ${now - refreshCache.timestamp}ms)`);
    return refreshCache.result;
  }

  // 2. 진행 중인 refresh가 있고, 아직 결과가 없으면 기다림 (실패한 결과는 캐시 안 함)
  if (refreshCache.promise && !refreshCache.result && now - refreshCache.timestamp < REFRESH_CACHE_TTL) {
    console.log(`🔵 [${caller}] Waiting for ongoing refresh...`);
    return refreshCache.promise;
  }

  // 2-1. 이전 refresh가 실패했으면 캐시 초기화
  if (refreshCache.result && !refreshCache.result.success) {
    console.log(`🔄 [${caller}] Previous refresh failed, clearing cache...`);
    refreshCache.promise = null;
    refreshCache.result = null;
  }

  // 3. 새 refresh 시작
  console.log(`🔄 [${caller}] Starting new refresh request...`);
  refreshCache.timestamp = now;
  refreshCache.result = null;

  refreshCache.promise = doRefreshToken(refreshToken).then(result => {
    refreshCache.result = result;
    return result;
  });

  return refreshCache.promise;
}

/**
 * 캐시 초기화 (테스트용)
 */
export function clearRefreshCache(): void {
  refreshCache = {
    promise: null,
    timestamp: 0,
    result: null,
  };
}