import { ref } from "vue";

/**
 * 공통 API 호출
 *
 * @param {string} method - 요청 메소드 (GET, POST 등)
 * @param {string} url - API URL
 * @param {object} query - 요청 쿼리 파라미터
 * @param {object} headers - 요청 헤더
 * @param {object} body - 요청 본문
 * @param {string} key - 캐시 키
 * @param {object} loading - 로딩 설정
 */
export const commonFetch = async (
  method:
    | "GET"
    | "HEAD"
    | "PATCH"
    | "POST"
    | "PUT"
    | "DELETE"
    | "CONNECT"
    | "OPTIONS"
    | "TRACE" = "GET", // Required
  url: string, // Required
  {
    query, // Optional
    headers, // Optional
    body, // Optional
    key, // Optional
    loading = false, // Optional
  }: {
    query?: object | null;
    headers?: object | null;
    body?: object | null;
    key?: string | null;
    loading?: { localId?: string } | boolean;
  } = {}
) => {
  let result = null;
  const currCallerId = ref("");
  const currCallerDetail = ref("");

  // 로딩 스토어 가져오기 (클라이언트에서만)
  let loadingStore: ReturnType<typeof useLoadingStore> | null = null;
  if (import.meta.client) {
    try {
      loadingStore = useLoadingStore();
      // 로딩 시작
      loadingStore.setLoading(true);
      if (loading && loadingStore) {
        if (typeof loading === "object" && loading.localId) {
          loadingStore.startLocalLoading(loading.localId);
        } else {
          loadingStore.startFullLoading();
        }
      }
    } catch (e) {
      console.warn("[Warning] Loading store not available:", e);
    }
  }

  try {
    const { callerId, callerDetail } = storeToRefs(useCallerInfoStore());
    currCallerId.value = `${callerId.value}`;
    currCallerDetail.value = `${callerDetail.value}`;
  } catch (e) {
    // SSR: pinia store 생성 전이므로 빈 값('') 세팅
  }

  try {
    const options: {
      method:
        | "GET"
        | "HEAD"
        | "PATCH"
        | "POST"
        | "PUT"
        | "DELETE"
        | "CONNECT"
        | "OPTIONS"
        | "TRACE";
      headers: Record<string, string>;
      query?: object;
      body?: object;
      key?: string;
    } = {
      method,
      headers: {
        "Content-Type": "application/json;charset=UTF-8",
      },
    };

    if (query) {
      options.query = query;
    }
    // 플랫폼 환경 API 호출 시 Caller-Id, Caller-Detail 헤더 추가
    if (url.includes(".onstove.com") || url.includes(".gate8.com")) {
      const callerInfo = {
        "Caller-Id": `${currCallerId.value}`,
        "Caller-Detail": `${currCallerDetail.value}`,
      };
      options.headers = { ...options.headers, ...callerInfo };
    }
    if (headers) {
      options.headers = { ...options.headers, ...headers };
    }
    if (body) {
      options.body = body;
    }
    if (key) {
      options.key = key;
    }

    result = await $fetch(url, options);
  } catch (e: unknown) {
    console.error("[Exception] apiUtil.commonFetch: ", e);
    const error = e as {
      data?: unknown;
      statusCode?: number;
      statusMessage?: string;
    };
    result = error.data || {
      code: error.statusCode,
      message: error.statusMessage,
    };
  } finally {
    // 로딩 종료
    if (loadingStore) {
      loadingStore.setLoading(false);
      if (loading) {
        if (typeof loading === "object" && loading.localId) {
          loadingStore.stopLocalLoading(loading.localId);
        } else {
          loadingStore.stopFullLoading();
        }
      }
    }
  }
  return result;
};

/**
 * 사용자 IP 조회
 *
 * @param {object} request - 요청 객체
 */
export const getTrueClientIp = (request: {
  headers: Record<string, string>;
  socket: { remoteAddress?: string };
}) => {
  const requestHeaders = request.headers;
  const targetHeaders = [
    "True-Client-IP",
    "X-Real-IP",
    "X-Forwarded-For",
    "Proxy-Client-IP",
    "WL-Proxy-Client-IP",
    "HTTP_CLIENT_IP",
    "HTTP_X_FORWARDED_FOR",
  ];
  for (const targetHeader of targetHeaders) {
    let ip =
      requestHeaders[targetHeader] ||
      requestHeaders[targetHeader.toLowerCase()];
    if (ip !== undefined && ip != null && ip !== "") {
      if (ip.includes(",")) {
        ip = ip.split(",")[0];
      }
      return ip;
    }
  }
  if (
    request.socket.remoteAddress !== undefined &&
    request.socket.remoteAddress != null &&
    request.socket.remoteAddress !== ""
  ) {
    return request.socket.remoteAddress;
  }
  return "";
};
