// Cliente HTTP base para todas las llamadas al API

const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || ""

export class ApiClient {
  private baseUrl: string
  private token: string | null = null

  constructor(baseUrl: string = API_BASE_URL) {
    this.baseUrl = baseUrl
    // Intentar recuperar el token del localStorage si existe
    if (typeof window !== "undefined") {
      this.token = localStorage.getItem("token")
    }
  }

  setToken(token: string | null) {
    this.token = token
    if (typeof window !== "undefined") {
      if (token) {
        localStorage.setItem("token", token)
      } else {
        localStorage.removeItem("token")
      }
    }
  }

  getToken(): string | null {
    return this.token
  }

  private getHeaders(customHeaders?: HeadersInit): HeadersInit {
    const headers: Record<string, string> = {
      "Content-Type": "application/json",
      ...(customHeaders as Record<string, string>),
    }

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

    return headers
  }

  async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    const url = `${this.baseUrl}${endpoint}`

    const config: RequestInit = {
      ...options,
      headers: this.getHeaders(options.headers),
    }

    try {
      const response = await fetch(url, config)

      if (!response.ok) {
        const errorData = await response.json().catch(() => ({}))
        throw {
          message: errorData.message || "Error en la petición",
          status: response.status,
          details: errorData,
        }
      }

      // Si la respuesta es 204 No Content, retornar objeto vacío
      if (response.status === 204) {
        return {} as T
      }

      return await response.json()
    } catch (error: any) {
      // Si es un error de red o el servidor no responde
      if (error.message === "Failed to fetch" || !error.status) {
        throw {
          message: "Error de conexión con el servidor",
          status: 0,
          details: error,
        }
      }
      throw error
    }
  }

  async get<T>(endpoint: string, params?: Record<string, any>): Promise<T> {
    const queryString = params ? "?" + new URLSearchParams(params).toString() : ""
    return this.request<T>(`${endpoint}${queryString}`, {
      method: "GET",
    })
  }

  async post<T>(endpoint: string, data?: any): Promise<T> {
    return this.request<T>(endpoint, {
      method: "POST",
      body: data ? JSON.stringify(data) : undefined,
    })
  }

  async put<T>(endpoint: string, data?: any): Promise<T> {
    return this.request<T>(endpoint, {
      method: "PUT",
      body: data ? JSON.stringify(data) : undefined,
    })
  }

  async delete<T>(endpoint: string): Promise<T> {
    return this.request<T>(endpoint, {
      method: "DELETE",
    })
  }

  async uploadFile<T>(endpoint: string, file: File, additionalData?: Record<string, any>): Promise<T> {
    const formData = new FormData()
    formData.append("file", file)

    if (additionalData) {
      Object.entries(additionalData).forEach(([key, value]) => {
        formData.append(key, String(value))
      })
    }

    const headers: HeadersInit = {}
    if (this.token) {
      headers["Authorization"] = `Bearer ${this.token}`
    }

    return this.request<T>(endpoint, {
      method: "POST",
      headers,
      body: formData,
    })
  }

  // Archivar trámite (soft delete)
  async archiveTramite(id: number): Promise<{ message: string }> {
    return this.request(`/tramites/${id}/archive`, {
      method: "POST",
    })
  }

  // Restaurar trámite archivado
  async restoreTramite(id: number): Promise<{ message: string }> {
    return this.request(`/tramites/${id}/restore`, {
      method: "POST",
    })
  }
}

// Instancia singleton del cliente
export const apiClient = new ApiClient()
