import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';
import type { LoginRequest, LoginResponse, Usuario, Progreso, Modulo, ProgresoModulo, Badge, ResumenProgreso } from '../types';

const API_BASE_URL = '/api';

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

let refreshPromise: Promise<string> | null = null;

const getStoredToken = () => localStorage.getItem('token');
const getStoredRefreshToken = () => localStorage.getItem('refresh_token');

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

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

    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;

      try {
        const refreshToken = getStoredRefreshToken();
        if (!refreshToken) {
          throw new Error('No refresh token');
        }

        if (!refreshPromise) {
          refreshPromise = refreshAccessToken(refreshToken);
        }

        const newToken = await refreshPromise;
        refreshPromise = null;

        localStorage.setItem('token', newToken);
        originalRequest.headers.Authorization = `Bearer ${newToken}`;

        return api(originalRequest);
      } catch (refreshError) {
        localStorage.removeItem('token');
        localStorage.removeItem('refresh_token');
        window.location.href = '/login';
        return Promise.reject(refreshError);
      }
    }

    return Promise.reject(error);
  }
);

async function refreshAccessToken(refreshToken: string): Promise<string> {
  const response = await axios.post(`${API_BASE_URL}/auth/refresh`, {
    refresh_token: refreshToken,
  });
  return response.data.access_token;
}

export const authService = {
  async login(credentials: LoginRequest): Promise<LoginResponse> {
    const response = await api.post<LoginResponse>('/auth/login', credentials);
    localStorage.setItem('token', response.data.access_token);
    localStorage.setItem('refresh_token', response.data.refresh_token);
    return response.data;
  },

  async logout(): Promise<void> {
    try {
      await api.post('/auth/logout');
    } finally {
      localStorage.removeItem('token');
      localStorage.removeItem('refresh_token');
    }
  },

  async getCurrentUser(): Promise<Usuario> {
    const response = await api.get<Usuario>('/auth/me');
    return response.data;
  },
};

export const progresoService = {
  async getProgreso(): Promise<Progreso[]> {
    const response = await api.get<Progreso[]>('/progreso');
    return response.data;
  },

  async saveProgreso(data: { modulo_numero: number; ejercicio_id: string; puntuacion: number; completado?: boolean }): Promise<Progreso> {
    const response = await api.post<Progreso>('/progreso', data);
    return response.data;
  },

  async getProgresoByUser(userId: string): Promise<Progreso[]> {
    const response = await api.get<Progreso[]>(`/admin/usuarios/${userId}/progreso`);
    return response.data;
  },

  async getResumen(): Promise<ResumenProgreso> {
    const response = await api.get<ResumenProgreso>('/progreso/resumen');
    return response.data;
  },

  async getResumenProgreso(): Promise<ResumenProgreso> {
    const response = await api.get<ResumenProgreso>('/progreso/resumen');
    return response.data;
  },

  async getProgresoModulos(): Promise<ProgresoModulo[]> {
    const response = await api.get<ProgresoModulo[]>('/progreso/modulos');
    return response.data;
  },

  async getBadges(): Promise<Badge[]> {
    const response = await api.get<Badge[]>('/progreso/badges');
    return response.data;
  },
};

export const moduloService = {
  async getModulos(): Promise<Modulo[]> {
    const response = await api.get<Modulo[]>('/contenido/modulos');
    return response.data;
  },

  async getModulo(numero: number): Promise<Modulo> {
    const response = await api.get<Modulo>(`/contenido/modulos/${numero}`);
    return response.data;
  },
};

export const usuarioService = {
  async getUsuarios(): Promise<Usuario[]> {
    const response = await api.get<Usuario[]>('/admin/usuarios');
    return response.data;
  },

  async createUsuario(usuario: Omit<Usuario, 'id'> & { password: string }): Promise<Usuario> {
    const response = await api.post<Usuario>('/admin/usuarios', usuario);
    return response.data;
  },

  async updateUsuario(id: string, usuario: Partial<Usuario>): Promise<Usuario> {
    const response = await api.put<Usuario>(`/admin/usuarios/${id}`, usuario);
    return response.data;
  },

  async deleteUsuario(id: string): Promise<void> {
    await api.delete(`/admin/usuarios/${id}`);
  },
};

export default api;
