import type { UseFetchOptions } from 'nuxt/app'
import type { ComputedRef } from 'vue'
import { useCapacitor } from './useCapacitor'
import type { ApiResponse } from '../types/api'
import { extractData, extractDataOrNull, isSuccessResponse, isErrorResponse } from '../types/api'

/**
 * Unified API client that handles:
 * - Base URL resolution (Capacitor vs web)
 * - Token injection (Bearer for Capacitor, cookies for web)
 * - Consistent error handling
 * - Type-safe API responses
 *
 * Use this instead of useApiCall() or useApiFetch()
 */
export function useApiClient() {
  const { isCapacitor, baseURL, getAuthToken } = useCapacitor()

  /**
   * Get authentication headers for API requests
   * - Capacitor: Bearer token from localStorage
   * - Web: Empty (cookies handled automatically)
   */
  const getAuthHeaders = (): HeadersInit => {
    if (!isCapacitor.value) {
      return {} // Cookies handled automatically for web
    }

    const token = getAuthToken()
    return token ? { Authorization: `Bearer ${token}` } : {}
  }

  /**
   * Make an API call using $fetch
   * Returns a standardized ApiResponse<T> wrapper
   * Use this for one-off API calls (not reactive)
   *
   * @example
   * const { apiCall } = useApiClient()
   * const response = await apiCall<User>('/api/user/profile')
   * if (response.success) {
   *   console.log(response.data) // Type-safe access to data
   * } else {
   *   console.error(response.error)
   * }
   *
   * @example - Using helper function
   * const { apiCall, extractData } = useApiClient()
   * const user = extractData(await apiCall<User>('/api/user/profile'))
   */
  const apiCall = async <T = unknown>(
    url: string,
    options?: Parameters<typeof $fetch>[1]
  ): Promise<ApiResponse<T>> => {
    const fullUrl = baseURL.value ? `${baseURL.value}${url}` : url

    try {
      const data = await $fetch(fullUrl, {
        ...options,
        headers: {
          ...getAuthHeaders(),
          ...options?.headers
        },
        credentials: 'include'
      })

      // If the response is already an ApiResponse, return it as-is
      if (data && typeof data === 'object' && 'success' in data) {
        return data as ApiResponse<T>
      }

      // Otherwise, wrap it in ApiResponse format
      return {
        success: true,
        data: data as T
      }
    } catch (error) {
      // Handle error responses
      const errorData = error as { data?: ApiResponse<never>, statusCode?: number, message?: string }

      // If error has ApiResponse format, return it
      if (errorData.data && typeof errorData.data === 'object' && 'success' in errorData.data) {
        return errorData.data as ApiResponse<T>
      }

      // Otherwise, create error response
      return {
        success: false,
        error: errorData.message || 'API request failed',
        statusCode: errorData.statusCode || 500
      }
    }
  }

  /**
   * Make a reactive API call using useFetch
   * Returns reactive refs with ApiResponse<T> format
   * Use this when you need reactive data (refs, loading states, etc.)
   *
   * @example
   * const { apiFetch } = useApiClient()
   * const { data, pending, error } = await apiFetch<User>('/api/user/profile')
   * // data.value will be ApiResponse<User> | null
   */
  const apiFetch = <T = unknown>(
    url: string,
    options?: UseFetchOptions<ApiResponse<T>>
  ) => {
    const fullUrl = baseURL.value ? `${baseURL.value}${url}` : url

    return useFetch<ApiResponse<T>>(fullUrl, {
      ...options,
      headers: {
        ...getAuthHeaders(),
        ...(options?.headers || {})
      },
      credentials: 'include',
      // Only force client-side for Capacitor (static builds)
      // On web, allow SSR for better performance and SEO
      server: isCapacitor.value ? false : (options?.server ?? true)
    } as UseFetchOptions<ApiResponse<T>>)
  }

  return {
    apiCall,
    apiFetch,
    isCapacitor,
    baseURL: baseURL.value,
    // Helper functions for working with ApiResponse
    extractData,
    extractDataOrNull,
    isSuccessResponse,
    isErrorResponse
  }
}
/**
 * Backward compatibility: Export useApiCall as a function that returns a callable
 * This maintains compatibility with existing code during migration
 *
 * Note: This version extracts data automatically for backward compatibility.
 * For type-safe responses, use useApiClient().apiCall() which returns ApiResponse<T>
 *
 * @deprecated Use useApiClient().apiCall() instead for type-safe ApiResponse<T>
 */
export const useApiCall = () => {
  const { apiCall, extractData } = useApiClient()
  // Return a wrapper that extracts data for backward compatibility
  return async <T = unknown>(
    url: string,
    options?: Parameters<typeof $fetch>[1]
  ): Promise<T> => {
    const response = await apiCall<T>(url, options)
    return extractData(response)
  }
}

/**
 * Backward compatibility: Export useApiFetch
 * Note: Returns data directly extracted from ApiResponse format
 * @deprecated Use useApiClient().apiFetch() instead
 */
export const useApiFetch = <T>(url: string, options?: UseFetchOptions<ApiResponse<T>>) => {
  const { apiFetch, extractDataOrNull } = useApiClient()
  const result = apiFetch<T>(url, options)

  // Transform data to extract from ApiResponse
  const extractedData = computed(() => {
    if (!result.data.value) return null
    return extractDataOrNull(result.data.value)
  }) as ComputedRef<T | null>

  return {
    ...result,
    data: extractedData
  }
}

/**
 * Returns the base URL for API requests
 * In Capacitor apps, this returns the full Vercel URL (set by the plugin)
 * In web apps, this returns empty string (relative paths work)
 * @deprecated Use useCapacitor().baseURL instead
 */
export const useApiBaseUrl = () => {
  const { baseURL } = useCapacitor()
  return baseURL.value
}
