import axios, { AxiosError } from "axios";
import { generateDeviceId } from "../utils/utils";
import { API_URL, TG_USER_ID } from "../constants/constants";

interface RpcRequest<TParams = unknown> {
  jsonrpc: string;
  method: string;
  params?: TParams;
  id?: string | number;
}

interface RpcResponse<TResult> {
  jsonrpc: string;
  result?: TResult;
  error?: { code: number; message: string };
  id?: string | number;
}

const apiClient = axios.create({
  baseURL: API_URL,
  timeout: 10000,
  headers: {
    "Content-Type": "application/json",
    "X-Auth-DeviceID": generateDeviceId(),
  },
});

apiClient.interceptors.request.use((config) => {
  const TOKEN = localStorage.getItem(`token-${TG_USER_ID}`);

  config.headers["X-Auth-SessionToken"] = TOKEN;
  return config;
});

export async function sendRpcRequest<TResponse, TParams = unknown>(
  method: string,
  params?: TParams,
  id: string | number = Date.now()
): Promise<TResponse> {
  const requestPayload: RpcRequest<TParams> = {
    jsonrpc: "2.0",
    method,
    params,
    id,
  };

  try {
    const { data } = await apiClient.post<RpcResponse<TResponse>>(
      "/",
      requestPayload
    );

    if (data.error) {
      if (data.error.code === 401 && data.error.message === "Invalid session") {
        localStorage.removeItem(`token-${TG_USER_ID}`);
        window.location.href = "/";
        return Promise.reject(new Error("Session expired. Redirecting..."));
      }

      throw new Error(data.error.message);
    }

    if (data.result === undefined) {
      throw new Error("No result returned from RPC response.");
    }

    return data.result;
  } catch (error) {
    const axiosError = error as AxiosError;

    if (axios.isAxiosError(axiosError)) {
      console.error(
        "Axios error:",
        axiosError.response?.data || axiosError.message
      );
    } else {
      console.error("Unexpected error:", error);
    }

    throw error;
  }
}

export default apiClient;
