import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios';
import { useAuthStore } from '@/stores/authStore';

const api = axios.create({
  baseURL: '/api',
  timeout: 15000,
  headers: { 'Content-Type': 'application/json' },
});

api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  const token = useAuthStore.getState().token;
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

let isRefreshing = false;
let failedQueue: Array<{
  resolve: (token: string) => void;
  reject: (error: unknown) => void;
}> = [];

function processQueue(error: unknown, token: string | null) {
  failedQueue.forEach((prom) => {
    if (error) prom.reject(error);
    else prom.resolve(token!);
  });
  failedQueue = [];
}

api.interceptors.response.use(
  (response) => response,
  async (error: AxiosError) => {
    const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };

    const isRefreshRequest = originalRequest.url === '/auth/refresh';

    if (error.response?.status === 401 && !originalRequest._retry && !isRefreshRequest) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        }).then((token) => {
          originalRequest.headers.Authorization = `Bearer ${token}`;
          return api(originalRequest);
        });
      }

      originalRequest._retry = true;
      isRefreshing = true;

      try {
        const refreshToken = useAuthStore.getState().refreshToken;
        if (!refreshToken) {
          throw new Error('Missing refresh token');
        }

        const { data } = await api.post('/auth/refresh', { refresh_token: refreshToken });
        const newToken = data.access_token ?? data.token;
        const newRefreshToken = data.refresh_token;
        useAuthStore.getState().setToken(newToken);
        if (newRefreshToken) {
          useAuthStore.getState().setRefreshToken(newRefreshToken);
        }
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        processQueue(null, newToken);
        return api(originalRequest);
      } catch (refreshError) {
        processQueue(refreshError, null);
        useAuthStore.getState().logout();
        return Promise.reject(refreshError);
      } finally {
        isRefreshing = false;
      }
    }

    return Promise.reject(error);
  }
);

export const authAPI = {
  register: (data: { username: string; email: string; password: string }) =>
    api.post('/auth/register', data),
  login: (data: { email: string; password: string }) =>
    api.post('/auth/login', data),
  refresh: (refreshToken: string) => api.post('/auth/refresh', { refresh_token: refreshToken }),
  logout: (refreshToken: string) => api.post('/auth/logout', { refresh_token: refreshToken }),
  steamRedirect: () => api.get('/auth/steam'),
  steamDevLink: (data: { steam_id: string }) => api.post('/auth/steam/dev-link', data),
};

export const profileAPI = {
  me: () => api.get('/profile'),
  getByUsername: (username: string) => api.get(`/profile/${username}`),
};

export const queueAPI = {
  join: (data: { game_mode: string }) => api.post('/queue/join', data),
  leave: () => api.post('/queue/leave'),
  status: () => api.get('/queue/status'),
};

export const matchAPI = {
  list: (params?: { page?: number; limit?: number }) =>
    api.get('/matches', { params }),
  get: (id: string) => api.get(`/matches/${id}`),
  getLive: (id: string) => api.get(`/matches/${id}/live`),
  getConnect: (id: string) => api.get(`/matches/${id}/connect`),
  leave: (id: string) => api.post(`/matches/${id}/leave`),
};

export const leaderboardAPI = {
  get: (params?: { page?: number; limit?: number }) =>
    api.get('/leaderboard', { params }),
};

export const supportAPI = {
  createTicket: (data: { category: string; subject: string; body: string }) =>
    api.post('/support/tickets', data),
  listTickets: (params?: { page?: number; limit?: number }) =>
    api.get('/support/tickets', { params }),
  getTicket: (id: string) => api.get(`/support/tickets/${id}`),
  addMessage: (id: string, data: { content: string }) =>
    api.post(`/support/tickets/${id}/messages`, data),
  closeTicket: (id: string) => api.post(`/support/tickets/${id}/close`),
};

export const adminAPI = {
  getUsers: (params?: Record<string, string>) => api.get('/admin/users', { params }),
  getUser: (id: string) => api.get(`/mod/users/${id}`),
  banUser: (id: string, data: { type: string; reason: string; duration?: string }) =>
    api.post(`/mod/users/${id}/ban`, data),
  unbanUser: (id: string) => api.post(`/mod/users/${id}/unban`),
  warnUser: (id: string, data: { reason: string }) =>
    api.post(`/mod/users/${id}/warn`, data),
  updateUserRole: (id: string, data: { role: string }) =>
    api.patch(`/admin/users/${id}/role`, data),
  updateUserTier: (id: string, data: { tier: string }) =>
    api.patch(`/admin/users/${id}/tier`, data),
  unlinkSteam: (id: string) => api.post(`/admin/users/${id}/unlink-steam`),
  getEloConfig: () => api.get('/admin/elo/config'),
  updateEloConfig: (data: Record<string, unknown>) => api.put('/admin/elo/config', data),
  getStats: () => api.get('/admin/stats'),
  getAuditLog: (params?: Record<string, string>) =>
    api.get('/admin/audit-log', { params }),
  getTickets: (params?: Record<string, string>) =>
    api.get('/mod/tickets', { params }),
  getTicket: (id: string) => api.get(`/mod/tickets/${id}`),
  replyTicket: (id: string, data: { content: string; is_internal?: boolean }) =>
    api.post(`/mod/tickets/${id}/messages`, data),
  assignTicket: (id: string) => api.post(`/mod/tickets/${id}/assign`),
  closeTicket: (id: string, data: { resolution: string }) =>
    api.post(`/mod/tickets/${id}/close`, data),
  getMatches: (params?: Record<string, string>) =>
    api.get('/mod/matches', { params }),
  cancelMatch: (id: string, data: { reason: string }) =>
    api.post(`/mod/matches/${id}/cancel`, data),
  nullifyMatch: (id: string, data: { reason: string }) =>
    api.post(`/mod/matches/${id}/nullify`, data),
  getUserHistory: (id: string) => api.get(`/mod/users/${id}/history`),
  addNote: (id: string, data: { content: string }) =>
    api.post(`/mod/users/${id}/note`, data),
  updateUser: (id: string, data: Record<string, unknown>) =>
    api.patch(`/admin/users/${id}`, data),
};

export const ownerAPI = {
  getConfig: () => api.get('/owner/config'),
  updateConfig: (data: Record<string, unknown>) => api.put('/owner/config', data),
  getSystem: () => api.get('/owner/system'),
  getContainers: () => api.get('/owner/system/containers'),
  restartContainer: (id: string) =>
    api.post(`/owner/system/containers/${id}/restart`),
  toggleMaintenance: () => api.post('/owner/maintenance'),
};

export default api;
