import * as SecureStore from 'expo-secure-store'
import { Platform } from 'react-native'

export const API_BASE_URL =
  process.env.EXPO_PUBLIC_API_URL?.replace(/\/$/, '') || 'https://socanum.com/api/v1'

const TOKEN_KEY = 'socanum_api_token'

export type ApiUser = {
  id: number
  name: string
  email: string
  username?: string | null
  phone?: string | null
  balance?: string
  currency?: string
}

type ApiEnvelope<T> = {
  success: boolean
  message?: string
  code?: string
  data: T
}

export type PaginatedResponse<T> = {
  data: T[]
  links?: Record<string, unknown>
  meta?: Record<string, unknown>
}

export type LoginResponse = {
  token_type: string
  access_token: string
  abilities: string[]
  user: ApiUser
}

export type DashboardData = {
  user: ApiUser
  stats: Record<string, number | string>
  recent_deposits: unknown[]
  recent_orders: unknown[]
  recent_numbers: unknown[]
}

export type WalletData = {
  balance: string
  currency: string
}

type RequestOptions = RequestInit & {
  token?: string | null
}

export async function getStoredToken() {
  if (Platform.OS === 'web') {
    return globalThis.localStorage?.getItem(TOKEN_KEY) ?? null
  }

  return SecureStore.getItemAsync(TOKEN_KEY)
}

export async function storeToken(token: string) {
  if (Platform.OS === 'web') {
    globalThis.localStorage?.setItem(TOKEN_KEY, token)
    return
  }

  await SecureStore.setItemAsync(TOKEN_KEY, token)
}

export async function clearStoredToken() {
  if (Platform.OS === 'web') {
    globalThis.localStorage?.removeItem(TOKEN_KEY)
    return
  }

  await SecureStore.deleteItemAsync(TOKEN_KEY)
}

export async function apiRequest<T>(path: string, options: RequestOptions = {}) {
  const token = options.token ?? (await getStoredToken())
  const response = await fetch(`${API_BASE_URL}${path}`, {
    ...options,
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...options.headers,
    },
  })

  const payload = (await response.json().catch(() => null)) as ApiEnvelope<T> | null

  if (!response.ok || payload?.success === false) {
    throw new Error(payload?.message || `Request failed with status ${response.status}`)
  }

  if (!payload) {
    throw new Error('The API returned an empty response.')
  }

  return payload.data
}

export function unwrapCollection<T>(payload: T[] | PaginatedResponse<T> | Record<string, unknown>) {
  if (Array.isArray(payload)) return payload

  if (
    payload &&
    typeof payload === 'object' &&
    'data' in payload &&
    Array.isArray((payload as PaginatedResponse<T>).data)
  ) {
    return (payload as PaginatedResponse<T>).data
  }

  return Object.values(payload || {}) as T[]
}

export function login(email: string, password: string) {
  return apiRequest<LoginResponse>('/auth/login', {
    method: 'POST',
    token: null,
    body: JSON.stringify({
      email,
      password,
      name: 'Socanum Mobile',
    }),
  })
}

export const endpoints = {
  me: () => apiRequest<{ user: ApiUser }>('/auth/me'),
  logout: () => apiRequest<never>('/auth/logout', { method: 'POST' }),
  dashboard: () => apiRequest<DashboardData>('/buyer/dashboard'),
  wallet: () => apiRequest<WalletData>('/wallet'),
  orders: () => apiRequest<PaginatedResponse<unknown>>('/buyer/orders'),
  logs: () => apiRequest<PaginatedResponse<unknown>>('/logs/categories'),
  numbersCountries: () => apiRequest<unknown[] | PaginatedResponse<unknown>>('/numbers/countries'),
  numbersServices: () => apiRequest<unknown[] | PaginatedResponse<unknown>>('/numbers/services'),
  boostCategories: () => apiRequest<unknown[] | PaginatedResponse<unknown>>('/boost/categories'),
  boostServices: () => apiRequest<unknown[] | PaginatedResponse<unknown>>('/boost/services'),
  tools: () => apiRequest<PaginatedResponse<unknown>>('/tools'),
}
