import axios from "axios";
import { useNavigate } from "react-router-dom";
import axiosRetry from "axios-retry";
import showToast from "../services/toastService";
import { startSignalR, stopSignalR } from "../services/signalRService";
import { BASE_URL } from "./constants";
import { decryptResponse } from "../services/encryption";
const base_Url = BASE_URL;

export const axiosClient = axios.create({
  baseURL: base_Url,
  withCredentials: false,
  headers: {
    "Content-Type": "application/json",
  },
});

// Auto retry failed requests (e.g., network issues)
axiosRetry(axiosClient, { retries: 3 });
//  Request Interceptor — Add Bearer token if required
axiosClient.interceptors.request.use(
  async (config) => {
    const requiresAuth = config.authRequired !== false; // default to true

    if (requiresAuth) {
      const token =
        localStorage.getItem("jwtToken") || sessionStorage.getItem("jwtToken");
      if (token) {
        config.headers["Authorization"] = `Bearer ${token}`;
        config._retry = true;
      } else {
        config._retry = false;
      }
    }

    return config;
  },
  (error) => Promise.reject(error)
);

// 🔄 Response Interceptor — Handle 401, refresh token, etc.
axiosClient.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;

    // Skip retry for public requests or already retried ones
    if (
      (!originalRequest && originalRequest._retry) ||
      originalRequest.authRequired === false
    ) {
      return Promise.reject(error);
    }

    // Avoid showing multiple toasts
    if (!originalRequest._toastShown) {
      originalRequest._toastShown = true;

      if (error.code === "ERR_CONNECTION_REFUSED") {
        showToast(
          "Unable to connect to the server. Please try again later.",
          "error"
        );
      } else if (error.code === "ERR_NETWORK") {
        showToast("Network error. Please check your connection.", "error");
        redirectToLogin();
      } else if (error.code === "ECONNABORTED") {
        showToast("Request timed out. Please try again.", "error");
      } else if (error.response) {
        const status = error.response.status;
        const isRefreshRequest = error.config.url.includes("refresh-token");

        if (status === 401 && !isRefreshRequest) {
          originalRequest._retry = true;

          const refreshToken =
            localStorage.getItem("refreshToken") ||
            sessionStorage.getItem("refreshToken");

          if (
            !refreshToken ||
            error.response.data?.errors === "Invalid or expired refresh token."
          ) {
            redirectToLogin();
            return Promise.reject(error);
          }

          stopSignalR();

          try {
            // Refresh token call
            const res = await axiosClient.post("/api/Auth/refresh-token", {
              token:
                localStorage.getItem("jwtToken") ||
                sessionStorage.getItem("jwtToken"),
              refreshToken,
            });

            const { token, refreshToken: newRefreshToken } = res.data.data;

            // Save updated tokens
            if (localStorage.getItem("jwtToken")) {
              localStorage.setItem("jwtToken", token);
              localStorage.setItem("refreshToken", newRefreshToken);
            } else {
              sessionStorage.setItem("jwtToken", token);
              sessionStorage.setItem("refreshToken", newRefreshToken);
            }

            startSignalR();
            // Set Authorization header
            originalRequest.headers["Authorization"] = `Bearer ${token}`;
            return axiosClient(originalRequest);
          } catch (refreshError) {
            redirectToLogin();
            return Promise.reject(refreshError);
          }
        }
      } else {
        showToast("An unknown error occurred.", "error");
      }
    }

    return Promise.reject(error);
  }
);

// Generic API function
const apiRequest = async (method, url, data = {}, config = {}) => {
  try {
    const response = await axiosClient({
      method,
      url,
      data: method !== "get" ? data : undefined,
      params: method === "get" ? data : undefined,
      ...config,
    });
    return  decryptResponse(response.data);
  } catch (error) {
    throw error;
  }
};

// Exported API wrapper
export const api = {
  // Public routes (no token required)
  postPublic: (url, data = {}, customHeaders = {}) =>
    apiRequest("post", url, data, {
      headers: { ...customHeaders },
      authRequired: false,
    }),
  getPublic: (url, data = {}, customHeaders = {}) =>
    apiRequest("get", url, data, {
      headers: { ...customHeaders },
      authRequired: false,
    }),

  // Authenticated routes
  get: (url, params = {}, customHeaders = {}) =>
    apiRequest("get", url, params, {
      headers: { ...customHeaders },
      authRequired: true,
    }),

  post: (url, data = {}, customHeaders = {}) =>
    apiRequest("post", url, data, {
      headers: { ...customHeaders },
      authRequired: true,
    }),

  put: (url, data = {}, customHeaders = {}) =>
    apiRequest("put", url, data, {
      headers: { ...customHeaders },
      authRequired: true,
    }),

  delete: (url, data = {}, customHeaders = {}) =>
    apiRequest("delete", url, data, {
      headers: { ...customHeaders },
      authRequired: true,
    }),
  patch: (url, data = {}, customHeaders = {}) =>
    apiRequest("patch", url, data, {
      headers: { ...customHeaders },
      authRequired: true,
    }),
};

// Redirect helper
function redirectToLogin() {
  window.location.href = "/auth/login";
}
