const API_URL = import.meta.env.VITE_API_URL || '/api'

interface ApiResponse<T = unknown> {
  data: T
  status: number
}

class ApiClient {
  private baseUrl: string

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl
  }

  private getToken(): string | null {
    return localStorage.getItem('accessToken')
  }

  private async request<T>(
    method: string,
    endpoint: string,
    data?: unknown,
    options?: { headers?: Record<string, string> }
  ): Promise<ApiResponse<T>> {
    const headers: Record<string, string> = {}

    const token = this.getToken()
    if (token) {
      headers['Authorization'] = `Bearer ${token}`
    }

    const config: RequestInit = {
      method,
      headers,
    }

    // Handle FormData (multipart/form-data) vs JSON
    if (data instanceof FormData) {
      config.body = data
      // Don't set Content-Type for FormData - browser will set it with boundary
    } else if (data) {
      headers['Content-Type'] = 'application/json'
      config.body = JSON.stringify(data)
    } else {
      headers['Content-Type'] = 'application/json'
    }
    
    // Merge custom headers
    if (options?.headers) {
      Object.assign(headers, options.headers)
      // Remove Content-Type if it's multipart (let browser handle it)
      if (options.headers['Content-Type']?.includes('multipart')) {
        delete headers['Content-Type']
      }
    }

    const response = await fetch(`${this.baseUrl}${endpoint}`, config)
    
    // Handle 401 - try to refresh token
    if (response.status === 401) {
      const refreshed = await this.tryRefreshToken()
      if (refreshed) {
        // Retry request with new token
        headers['Authorization'] = `Bearer ${this.getToken()}`
        const retryResponse = await fetch(`${this.baseUrl}${endpoint}`, {
          ...config,
          headers,
        })
        const retryData = await retryResponse.json()
        return { data: retryData, status: retryResponse.status }
      }
    }

    const responseData = await response.json()

    if (!response.ok) {
      throw new Error(responseData.error || 'Request failed')
    }

    return { data: responseData, status: response.status }
  }

  private async tryRefreshToken(): Promise<boolean> {
    const refreshToken = localStorage.getItem('refreshToken')
    if (!refreshToken) return false

    try {
      const response = await fetch(`${this.baseUrl}/auth/refresh`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ refreshToken }),
      })

      if (!response.ok) return false

      const data = await response.json()
      localStorage.setItem('accessToken', data.accessToken)
      return true
    } catch {
      return false
    }
  }

  get<T>(endpoint: string): Promise<ApiResponse<T>> {
    return this.request<T>('GET', endpoint)
  }

  post<T>(endpoint: string, data?: unknown, options?: { headers?: Record<string, string> }): Promise<ApiResponse<T>> {
    return this.request<T>('POST', endpoint, data, options)
  }

  put<T>(endpoint: string, data?: unknown): Promise<ApiResponse<T>> {
    return this.request<T>('PUT', endpoint, data)
  }

  delete<T>(endpoint: string): Promise<ApiResponse<T>> {
    return this.request<T>('DELETE', endpoint)
  }
}

export const api = new ApiClient(API_URL)
