import axios from 'axios';
import { api, apiClient } from '@/shared/utils/api';
import { API_ENDPOINTS } from '@/shared/constants/apiEndpoints';
import { getDeviceFingerprint } from '@/features/auth/utils/deviceFingerprint';
import type { User } from '@/shared/types/api.types';

type MeResponse = {
  data: User;
};

type AuthUserResponse = {
  data: User;
};

type MessageResponse = {
  message: string;
  retry_after_seconds?: number;
};

const csrfClient = axios.create({
  withCredentials: true,
  headers: {
    Accept: 'application/json',
    'X-Requested-With': 'XMLHttpRequest',
  },
});

export const authService = {
  async ensureCsrfCookie(): Promise<void> {
    await csrfClient.get('/sanctum/csrf-cookie');
  },

  async requestOtp(email: string): Promise<MessageResponse> {
    return api.post<MessageResponse>(API_ENDPOINTS.AUTH.REQUEST_OTP, {
      email,
      device_fingerprint: getDeviceFingerprint(),
    });
  },

  async verifyOtp(
    email: string,
    otp: string,
    rememberDevice = false,
  ): Promise<User> {
    const response = await api.post<AuthUserResponse>(API_ENDPOINTS.AUTH.VERIFY_OTP, {
      email,
      otp,
      remember_device: rememberDevice,
      device_fingerprint: getDeviceFingerprint(),
    });

    return response.data;
  },

  async requestMagicLink(email: string): Promise<MessageResponse> {
    return api.post<MessageResponse>(API_ENDPOINTS.AUTH.REQUEST_MAGIC_LINK, {
      email,
      device_fingerprint: getDeviceFingerprint(),
    });
  },

  async verifyMagicLink(
    email: string,
    token: string,
    rememberDevice = false,
  ): Promise<User> {
    const response = await api.post<AuthUserResponse>(API_ENDPOINTS.AUTH.VERIFY_MAGIC_LINK, {
      email,
      token,
      remember_device: rememberDevice,
      device_fingerprint: getDeviceFingerprint(),
    });

    return response.data;
  },

  async acceptInvite(email: string, token: string, name: string): Promise<void> {
    await api.post(API_ENDPOINTS.AUTH.ACCEPT_INVITE, { email, token, name });
  },

  async fetchMe(): Promise<User> {
    const response = await api.get<MeResponse>(API_ENDPOINTS.AUTH.ME);
    return response.data;
  },

  /** Returns null when there is no active session (avoids treating 401 as an error). */
  async validateSession(): Promise<User | null> {
    const response = await apiClient.get<MeResponse>(API_ENDPOINTS.AUTH.ME, {
      validateStatus: (status) => status === 200 || status === 401,
    });

    if (response.status === 401) {
      return null;
    }

    return response.data.data;
  },

  async logout(): Promise<void> {
    await api.post(API_ENDPOINTS.AUTH.LOGOUT);
  },

  async listSessions(): Promise<AuthSession[]> {
    const response = await api.get<{ data: AuthSession[] }>(API_ENDPOINTS.AUTH.SESSIONS);
    return response.data;
  },

  async revokeSession(sessionId: string): Promise<void> {
    await api.delete(API_ENDPOINTS.AUTH.SESSION(sessionId));
  },

  async revokeOtherSessions(): Promise<void> {
    await api.delete(API_ENDPOINTS.AUTH.SESSIONS_REVOKE_OTHERS);
  },

  async revokeCurrentSession(): Promise<void> {
    await api.delete(API_ENDPOINTS.AUTH.SESSIONS_CURRENT);
  },
};

export interface AuthSession {
  id: string;
  device_name: string;
  ip_address: string | null;
  last_used_at: string | null;
  trusted_until: string | null;
  is_trusted: boolean;
  is_current: boolean;
  created_at: string;
}
