import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';

export interface APIClientConfig {
  baseURL: string;
  timeout?: number;
  headers?: Record<string, string>;
}

export interface AuthTokens {
  accessToken: string;
  refreshToken?: string;
}

class APIClient {
  private client: AxiosInstance;
  private tokens: AuthTokens | null = null;

  constructor(config: APIClientConfig) {
    this.client = axios.create({
      baseURL: config.baseURL,
      timeout: config.timeout || 30000,
      headers: {
        'Content-Type': 'application/json',
        ...config.headers,
      },
    });

    // Request interceptor - add auth token
    this.client.interceptors.request.use((config) => {
      if (this.tokens?.accessToken) {
        config.headers.Authorization = `Bearer ${this.tokens.accessToken}`;
      }
      return config;
    });

    // Response interceptor - handle token refresh
    this.client.interceptors.response.use(
      (response) => response,
      async (error) => {
        if (error.response?.status === 401 && this.tokens?.refreshToken) {
          try {
            const newTokens = await this.refreshAccessToken();
            this.setTokens(newTokens);
            
            // Retry original request
            error.config.headers.Authorization = `Bearer ${newTokens.accessToken}`;
            return this.client.request(error.config);
          } catch (refreshError) {
            // Refresh failed, clear tokens
            this.clearTokens();
            throw refreshError;
          }
        }
        throw error;
      }
    );
  }

  setTokens(tokens: AuthTokens) {
    this.tokens = tokens;
  }

  clearTokens() {
    this.tokens = null;
  }

  private async refreshAccessToken(): Promise<AuthTokens> {
    const response = await this.client.post('/auth/refresh', {
      refreshToken: this.tokens?.refreshToken,
    });
    return response.data;
  }

  // Auth
  async login(email: string, password: string) {
    const response = await this.client.post('/auth/login', { email, password });
    return response.data;
  }

  async register(email: string, password: string, username: string) {
    const response = await this.client.post('/auth/register', {
      email,
      password,
      username,
    });
    return response.data;
  }

  async getCurrentUser() {
    const response = await this.client.get('/auth/me');
    return response.data;
  }

  // Messages
  async getConversations() {
    const response = await this.client.get('/conversations');
    return response.data;
  }

  async getMessages(conversationId: string, limit = 50, before?: string) {
    const response = await this.client.get(`/messages/${conversationId}`, {
      params: { limit, before },
    });
    return response.data;
  }

  async sendMessage(conversationId: string, content: string, contentType = 'text') {
    const response = await this.client.post('/messages', {
      conversationId,
      content,
      contentType,
    });
    return response.data;
  }

  // Friends (Nexus)
  async getFriends() {
    const response = await this.client.get('/nexus/friends');
    return response.data;
  }

  async sendFriendRequest(userId: string) {
    const response = await this.client.post('/nexus/friends/request', { userId });
    return response.data;
  }

  async acceptFriendRequest(requestId: string) {
    const response = await this.client.post(`/nexus/friends/accept/${requestId}`);
    return response.data;
  }

  // Calls
  async initiateCall(recipientId: string, callType: 'voice' | 'video') {
    const response = await this.client.post('/calls/initiate', {
      recipientId,
      callType,
    });
    return response.data;
  }

  async joinCall(callId: string) {
    const response = await this.client.post(`/calls/join/${callId}`);
    return response.data;
  }

  async leaveCall(callId: string) {
    const response = await this.client.post(`/calls/leave/${callId}`);
    return response.data;
  }

  // Premium
  async checkDomainAvailability(domain: string) {
    const response = await this.client.post('/premium/domains/check-availability', {
      domain,
    });
    return response.data;
  }

  async subscribe(tier: string, paymentMethodId: string, billingPeriod: string) {
    const response = await this.client.post('/premium/subscribe', {
      tier,
      paymentMethodId,
      billingPeriod,
    });
    return response.data;
  }

  async getSubscription() {
    const response = await this.client.get('/premium/subscription');
    return response.data;
  }

  async getAnalytics(period: string = '30d') {
    const response = await this.client.get('/premium/analytics', {
      params: { period },
    });
    return response.data;
  }

  // Generic request method
  async request<T = any>(config: AxiosRequestConfig): Promise<T> {
    const response = await this.client.request<T>(config);
    return response.data;
  }
}

export default APIClient;
