import type { AdminStats, Drink, DrinkCreate, Invitation, TokenResponse, User } from './types'

const BASE = '/api'

let authToken: string | null = sessionStorage.getItem('cellar_token')

export function setToken(token: string | null) {
  authToken = token
  if (token) {
    sessionStorage.setItem('cellar_token', token)
  } else {
    sessionStorage.removeItem('cellar_token')
  }
}

export function getToken(): string | null {
  return authToken
}

async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
  const headers: Record<string, string> = {
    ...(options.headers as Record<string, string>),
  }

  if (authToken) {
    headers['Authorization'] = `Bearer ${authToken}`
  }

  if (!(options.body instanceof FormData)) {
    headers['Content-Type'] = 'application/json'
  }

  const res = await fetch(`${BASE}${url}`, { ...options, headers })

  if (res.status === 401) {
    setToken(null)
    window.location.href = '/login'
    throw new Error('Session expirée')
  }

  if (!res.ok) {
    const err = await res.json().catch(() => ({ detail: 'Erreur inconnue' }))
    let msg = err.detail || `Erreur ${res.status}`
    if (Array.isArray(msg)) {
      msg = msg.map((e: { msg?: string }) => e.msg || JSON.stringify(e)).join(', ')
    }
    throw new Error(msg)
  }

  return res.json()
}

export const api = {
  // Auth
  login(username: string, password: string): Promise<TokenResponse> {
    return request('/auth/login', {
      method: 'POST',
      body: JSON.stringify({ username, password }),
    })
  },

  register(username: string, email: string, password: string, invite_token: string): Promise<TokenResponse> {
    return request('/auth/register', {
      method: 'POST',
      body: JSON.stringify({ username, email, password, invite_token }),
    })
  },

  me(): Promise<User> {
    return request('/auth/me')
  },

  changePassword(currentPassword: string, newPassword: string): Promise<void> {
    return request('/auth/change-password', {
      method: 'POST',
      body: JSON.stringify({ current_password: currentPassword, new_password: newPassword }),
    })
  },

  logout(): Promise<void> {
    return request('/auth/logout', { method: 'POST' })
  },

  createInvitation(): Promise<Invitation> {
    return request('/auth/invitations', { method: 'POST' })
  },

  listInvitations(): Promise<Invitation[]> {
    return request('/auth/invitations')
  },

  // Drinks
  listDrinks(params?: {
    category?: string
    search?: string
    min_rating?: number
  }): Promise<Drink[]> {
    const searchParams = new URLSearchParams()
    if (params?.category) searchParams.set('category', params.category)
    if (params?.search) searchParams.set('search', params.search)
    if (params?.min_rating) searchParams.set('min_rating', String(params.min_rating))
    const qs = searchParams.toString()
    return request(`/drinks${qs ? `?${qs}` : ''}`)
  },

  getDrink(id: number): Promise<Drink> {
    return request(`/drinks/${id}`)
  },

  createDrink(drink: DrinkCreate): Promise<Drink> {
    return request('/drinks', {
      method: 'POST',
      body: JSON.stringify(drink),
    })
  },

  updateDrink(id: number, updates: Partial<DrinkCreate>): Promise<Drink> {
    return request(`/drinks/${id}`, {
      method: 'PUT',
      body: JSON.stringify(updates),
    })
  },

  deleteDrink(id: number): Promise<void> {
    return request(`/drinks/${id}`, { method: 'DELETE' })
  },

  async uploadImage(drinkId: number, file: File): Promise<Drink> {
    const formData = new FormData()
    formData.append('file', file)
    return request(`/drinks/${drinkId}/upload-image`, {
      method: 'POST',
      body: formData,
    })
  },

  // Admin
  adminListUsers(): Promise<User[]> {
    return request('/admin/users')
  },

  adminDeleteUser(userId: number): Promise<void> {
    return request(`/admin/users/${userId}`, { method: 'DELETE' })
  },

  adminResetPassword(userId: number, newPassword: string): Promise<void> {
    return request(`/admin/users/${userId}/reset-password`, {
      method: 'POST',
      body: JSON.stringify({ new_password: newPassword }),
    })
  },

  adminToggleAdmin(userId: number, isAdmin: boolean): Promise<void> {
    return request(`/admin/users/${userId}/toggle-admin`, {
      method: 'POST',
      body: JSON.stringify({ is_admin: isAdmin }),
    })
  },

  adminStats(): Promise<AdminStats> {
    return request('/admin/stats')
  },
}
