import type {
  ApiResponse,
  CreateExchangeRequest,
  CreateProviderMappingRequest,
  Exchange,
  ExchangeDetails,
  ExchangeStats,
  ProviderExchange,
  ProviderMapping,
  UpdateExchangeRequest,
  UpdateProviderMappingRequest,
} from '../types/index';

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:2003';

class ExchangeApiService {
  private async request<T>(endpoint: string, options?: RequestInit): Promise<ApiResponse<T>> {
    const url = `${API_BASE_URL}/api${endpoint}`;

    const response = await fetch(url, {
      headers: {
        'Content-Type': 'application/json',
        ...options?.headers,
      },
      ...options,
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const data = await response.json();

    if (!data.success) {
      throw new Error(data.error || 'API request failed');
    }

    return data;
  }

  // Exchanges
  async getExchanges(): Promise<Exchange[]> {
    const response = await this.request<Exchange[]>('/exchanges');
    return response.data || [];
  }

  async getExchangeById(id: string): Promise<ExchangeDetails | null> {
    const response = await this.request<ExchangeDetails>(`/exchanges/${id}`);
    return response.data || null;
  }

  async createExchange(data: CreateExchangeRequest): Promise<Exchange> {
    const response = await this.request<Exchange>('/exchanges', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    if (!response.data) {
      throw new Error('No exchange data returned');
    }
    return response.data;
  }

  async updateExchange(id: string, data: UpdateExchangeRequest): Promise<Exchange> {
    const response = await this.request<Exchange>(`/exchanges/${id}`, {
      method: 'PATCH',
      body: JSON.stringify(data),
    });
    if (!response.data) {
      throw new Error('No exchange data returned');
    }
    return response.data;
  }

  // Provider Mappings
  async getProviderMappings(provider?: string): Promise<ProviderMapping[]> {
    const endpoint = provider
      ? `/exchanges/provider-mappings/${provider}`
      : '/exchanges/provider-mappings/all';

    const response = await this.request<ProviderMapping[]>(endpoint);
    return response.data || [];
  }

  async createProviderMapping(data: CreateProviderMappingRequest): Promise<ProviderMapping> {
    const response = await this.request<ProviderMapping>('/exchanges/provider-mappings', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    if (!response.data) {
      throw new Error('No provider mapping data returned');
    }
    return response.data;
  }

  async updateProviderMapping(
    id: string,
    data: UpdateProviderMappingRequest
  ): Promise<ProviderMapping> {
    const response = await this.request<ProviderMapping>(`/exchanges/provider-mappings/${id}`, {
      method: 'PATCH',
      body: JSON.stringify(data),
    });
    if (!response.data) {
      throw new Error('No provider mapping data returned');
    }
    return response.data;
  }

  // Providers and Utilities
  async getProviders(): Promise<string[]> {
    const response = await this.request<string[]>('/exchanges/providers/list');
    return response.data || [];
  }

  async getUnmappedProviderExchanges(provider: string): Promise<ProviderExchange[]> {
    const response = await this.request<ProviderExchange[]>(
      `/exchanges/provider-exchanges/unmapped/${provider}`
    );
    return response.data || [];
  }

  async getExchangeStats(): Promise<ExchangeStats> {
    const response = await this.request<ExchangeStats>('/exchanges/stats/summary');
    if (!response.data) {
      throw new Error('No exchange stats data returned');
    }
    return response.data;
  }
}

// Export singleton instance
export const exchangeApi = new ExchangeApiService();
