const BASE = '/api'

// ─── Token helpers ────────────────────────────────────────────────────────────

export function getToken()          { return localStorage.getItem('token') }
export function setToken(t)         { t ? localStorage.setItem('token', t) : localStorage.removeItem('token') }

function authHeaders(extra = {}) {
  const token = getToken()
  return token
    ? { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, ...extra }
    : { 'Content-Type': 'application/json', ...extra }
}

async function handleResponse(res) {
  if (res.status === 401) {
    setToken(null)
    window.dispatchEvent(new Event('auth:expired'))
    throw new Error('Session expirée, veuillez vous reconnecter.')
  }
  if (!res.ok) {
    const err = await res.json().catch(() => ({}))
    throw new Error(err.detail ?? `HTTP ${res.status}`)
  }
  return res.json()
}

// ─── Auth ─────────────────────────────────────────────────────────────────────

export async function authStatus() {
  const res = await fetch(`${BASE}/auth/status`)
  return handleResponse(res)
}

export async function register(username, password) {
  const res = await fetch(`${BASE}/auth/register`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password }),
  })
  return handleResponse(res)
}

export async function login(username, password) {
  const res = await fetch(`${BASE}/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password }),
  })
  return handleResponse(res)
}

// ─── VPS ──────────────────────────────────────────────────────────────────────

export async function fetchAllStatus() {
  const res = await fetch(`${BASE}/status`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function fetchLogs(vpsId, containerId, lines = 200) {
  const res = await fetch(
    `${BASE}/vps/${vpsId}/containers/${containerId}/logs?lines=${lines}`,
    { headers: authHeaders() }
  )
  return handleResponse(res)
}

export async function containerAction(vpsId, containerId, action) {
  const res = await fetch(`${BASE}/vps/${vpsId}/containers/${containerId}/action`, {
    method: 'POST',
    headers: authHeaders(),
    body: JSON.stringify({ action }),
  })
  return handleResponse(res)
}

export async function addVps(data) {
  const res = await fetch(`${BASE}/vps`, {
    method: 'POST',
    headers: authHeaders(),
    body: JSON.stringify(data),
  })
  return handleResponse(res)
}

export async function deleteVps(vpsId) {
  const res = await fetch(`${BASE}/vps/${vpsId}`, {
    method: 'DELETE',
    headers: authHeaders(),
  })
  return handleResponse(res)
}

export async function composeUpdate(vpsId, project) {
  const res = await fetch(`${BASE}/vps/${vpsId}/compose/update`, {
    method: 'POST',
    headers: authHeaders(),
    body: JSON.stringify({ project }),
  })
  return handleResponse(res)
}

export async function updateAgent(vpsId) {
  const res = await fetch(`${BASE}/vps/${vpsId}/agent/update`, {
    method: 'POST',
    headers: authHeaders(),
  })
  return handleResponse(res)
}

export async function updateVps(vpsId, data) {
  const res = await fetch(`${BASE}/vps/${vpsId}`, {
    method: 'PUT',
    headers: authHeaders(),
    body: JSON.stringify(data),
  })
  return handleResponse(res)
}

export async function exportVps(vpsId) {
  const res = await fetch(`${BASE}/vps/${vpsId}/export`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function fetchVpsStats(vpsId, duration = 600) {
  const res = await fetch(`${BASE}/vps/${vpsId}/stats?duration=${duration}`, { headers: authHeaders() })
  return handleResponse(res)
}

// ─── Profile ──────────────────────────────────────────────────────────────────

export async function changePassword(oldPassword, newPassword) {
  const res = await fetch(`${BASE}/auth/change-password`, {
    method: 'POST',
    headers: authHeaders(),
    body: JSON.stringify({ old_password: oldPassword, new_password: newPassword }),
  })
  return handleResponse(res)
}

// ─── Admin ────────────────────────────────────────────────────────────────────

export async function getAdminSettings() {
  const res = await fetch(`${BASE}/admin/settings`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function setAdminSetting(key, value) {
  const res = await fetch(`${BASE}/admin/settings/${key}`, {
    method: 'PUT',
    headers: authHeaders(),
    body: JSON.stringify({ value }),
  })
  return handleResponse(res)
}

export async function getLoginLogs(limit = 100, offset = 0) {
  const res = await fetch(`${BASE}/admin/login-logs?limit=${limit}&offset=${offset}`, {
    headers: authHeaders(),
  })
  return handleResponse(res)
}

export async function getAdminUsers() {
  const res = await fetch(`${BASE}/admin/users`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function getDbInfo() {
  const res = await fetch(`${BASE}/admin/db/info`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function purgeDb({ table, period, fromTs, toTs }) {
  const body = { table, period }
  if (period === 'custom') {
    body.from_ts = fromTs
    body.to_ts   = toTs
  }
  const res = await fetch(`${BASE}/admin/db/purge`, {
    method: 'DELETE',
    headers: authHeaders(),
    body: JSON.stringify(body),
  })
  return handleResponse(res)
}

// ─── Passkeys (WebAuthn) ──────────────────────────────────────────────────────

function _b64url(buffer) {
  const bytes = new Uint8Array(buffer)
  let str = ''
  for (const b of bytes) str += String.fromCharCode(b)
  return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
}

function _fromB64url(str) {
  const padding = '='.repeat((4 - (str.length % 4)) % 4)
  const base64  = (str + padding).replace(/-/g, '+').replace(/_/g, '/')
  const binary  = atob(base64)
  const bytes   = new Uint8Array(binary.length)
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)
  return bytes.buffer
}

function _prepareRegistrationOptions(opts) {
  return {
    ...opts,
    challenge:          _fromB64url(opts.challenge),
    user:               { ...opts.user, id: _fromB64url(opts.user.id) },
    excludeCredentials: (opts.excludeCredentials || []).map(c => ({ ...c, id: _fromB64url(c.id) })),
  }
}

function _prepareAuthenticationOptions(opts) {
  return {
    ...opts,
    challenge:          _fromB64url(opts.challenge),
    allowCredentials:   (opts.allowCredentials || []).map(c => ({ ...c, id: _fromB64url(c.id) })),
  }
}

function _serializeRegistrationCredential(cred) {
  return {
    id:       cred.id,
    rawId:    _b64url(cred.rawId),
    type:     cred.type,
    response: {
      clientDataJSON:    _b64url(cred.response.clientDataJSON),
      attestationObject: _b64url(cred.response.attestationObject),
    },
  }
}

function _serializeAuthenticationCredential(cred) {
  const out = {
    id:       cred.id,
    rawId:    _b64url(cred.rawId),
    type:     cred.type,
    response: {
      clientDataJSON:  _b64url(cred.response.clientDataJSON),
      authenticatorData: _b64url(cred.response.authenticatorData),
      signature:       _b64url(cred.response.signature),
    },
  }
  if (cred.response.userHandle) {
    out.response.userHandle = _b64url(cred.response.userHandle)
  }
  return out
}

/** Lance l'enregistrement complet d'une passkey (begin → browser → finish). */
export async function registerPasskey(name) {
  // 1. Obtenir le challenge
  const beginRes = await fetch(`${BASE}/auth/passkey/register/begin`, {
    method: 'POST',
    headers: authHeaders(),
  })
  const { session_id, options } = await handleResponse(beginRes)

  // 2. Appel biométrique
  const cred = await navigator.credentials.create({
    publicKey: _prepareRegistrationOptions(options),
  })

  // 3. Finaliser
  const finishRes = await fetch(`${BASE}/auth/passkey/register/finish`, {
    method: 'POST',
    headers: authHeaders(),
    body: JSON.stringify({ session_id, name, credential: _serializeRegistrationCredential(cred) }),
  })
  return handleResponse(finishRes)
}

/** Authentification complète par passkey (begin → browser → finish). Retourne {access_token, role}. */
export async function loginWithPasskey(username = null) {
  // 1. Obtenir le challenge
  const beginRes = await fetch(`${BASE}/auth/passkey/login/begin`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username }),
  })
  const { session_id, options } = await handleResponse(beginRes)

  // 2. Appel biométrique (TouchID / FaceID)
  const cred = await navigator.credentials.get({
    publicKey: _prepareAuthenticationOptions(options),
  })

  // 3. Vérification côté serveur
  const finishRes = await fetch(`${BASE}/auth/passkey/login/finish`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ session_id, credential: _serializeAuthenticationCredential(cred) }),
  })
  return handleResponse(finishRes)
}

export async function getMyPasskeys() {
  const res = await fetch(`${BASE}/auth/passkeys`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function deleteMyPasskey(credentialId) {
  const res = await fetch(`${BASE}/auth/passkeys/${encodeURIComponent(credentialId)}`, {
    method: 'DELETE',
    headers: authHeaders(),
  })
  return handleResponse(res)
}

export async function adminGetPasskeys() {
  const res = await fetch(`${BASE}/admin/passkeys`, { headers: authHeaders() })
  return handleResponse(res)
}

export async function adminDeletePasskey(credentialId) {
  const res = await fetch(`${BASE}/admin/passkeys/${encodeURIComponent(credentialId)}`, {
    method: 'DELETE',
    headers: authHeaders(),
  })
  return handleResponse(res)
}

// ─── Notifications / Container events ────────────────────────────────────────

export async function getContainerEvents(limit = 100, offset = 0) {
  const res = await fetch(`${BASE}/admin/container-events?limit=${limit}&offset=${offset}`, {
    headers: authHeaders(),
  })
  return handleResponse(res)
}

export async function testPushoverNotification() {
  const res = await fetch(`${BASE}/admin/notifications/test`, {
    method: 'POST',
    headers: authHeaders(),
  })
  return handleResponse(res)
}
