// Thin fetch wrapper. Always sends cookies (httpOnly JWT) and talks to the
// same-origin API (/api/v1) — proxied to the Express server in dev.
const BASE = '/api/v1'

class ApiError extends Error {
  constructor(status, message, body) {
    super(message)
    this.status = status
    this.body = body
  }
}

async function req(path, { method = 'GET', body, headers, raw } = {}) {
  const opts = { method, credentials: 'include', headers: { ...headers } }
  if (body !== undefined) {
    if (raw) {
      opts.body = body // FormData — let the browser set the content-type
    } else {
      opts.headers['Content-Type'] = 'application/json'
      opts.body = JSON.stringify(body)
    }
  }
  const res = await fetch(BASE + path, opts)
  const text = await res.text()
  const data = text ? safeParse(text) : null
  if (!res.ok) {
    const message = (data && data.message) || res.statusText || 'Request failed'
    throw new ApiError(res.status, message, data)
  }
  return data
}

function safeParse(text) {
  try {
    return JSON.parse(text)
  } catch {
    return text
  }
}

export const api = {
  // ----- auth -----
  me: () => req('/auth/me'),
  // `extra` carries the honeypot field (and any future login fields).
  login: (username, password, extra = {}) =>
    req('/auth/login', { method: 'POST', body: { username, password, ...extra } }),
  loginTotp: (challenge, code) =>
    req('/auth/login/totp', { method: 'POST', body: { challenge, code } }),
  // Second factor for an SSO login (challenge is held in an httpOnly cookie set by
  // the callback, so only the code is sent). Returns { user, returnTo }.
  ssoLoginTotp: (code) => req('/auth/sso/totp', { method: 'POST', body: { code } }),
  logout: () => req('/auth/logout', { method: 'POST' }),
  // Public SSO provider discovery — drives the login-page provider buttons.
  authProviders: () => req('/auth/providers'),

  // ----- public -----
  publicSettings: () => req('/public/settings'),
  status: () => req('/public/status'),
  posts: (category) => req(`/public/posts/${category}`),
  post: (category, idOrSlug) => req(`/public/posts/${category}/${idOrSlug}`),
  wiki: (opts = {}) => {
    const qs = new URLSearchParams()
    if (opts.category) qs.set('category', opts.category)
    if (opts.tag) qs.set('tag', opts.tag)
    if (opts.q) qs.set('q', opts.q)
    const s = qs.toString()
    return req(`/public/wiki${s ? `?${s}` : ''}`)
  },
  wikiCategories: () => req('/public/wiki/categories'),
  wikiTags: () => req('/public/wiki/tags'),
  wikiPage: (slug) => req(`/public/wiki/${slug}`),
  contact: (payload) => req('/public/contact', { method: 'POST', body: payload }),

  // ----- admin -----
  admin: {
    dashboard: () => req('/admin/dashboard'),
    setSiteMode: (mode) => req('/admin/site-mode', { method: 'PUT', body: { mode } }),
    listPosts: (category) => req(`/admin/posts${category ? `?category=${category}` : ''}`),
    getPost: (id) => req(`/admin/posts/${id}`),
    createPost: (data) => req('/admin/posts', { method: 'POST', body: data }),
    updatePost: (id, data) => req(`/admin/posts/${id}`, { method: 'PUT', body: data }),
    deletePost: (id) => req(`/admin/posts/${id}`, { method: 'DELETE' }),
    publishPost: (id, published) =>
      req(`/admin/posts/${id}/publish`, { method: 'PATCH', body: { published } }),
    uploadImage: (file) => {
      const fd = new FormData()
      fd.append('image', file)
      return req('/admin/posts/upload', { method: 'POST', body: fd, raw: true })
    },
    // Generalized upload for rich-text editors → { url }.
    upload: (file) => {
      const fd = new FormData()
      fd.append('image', file)
      return req('/admin/uploads', { method: 'POST', body: fd, raw: true })
    },
    listWiki: (params = '') => req(`/admin/wiki${params}`),
    getWiki: (slug) => req(`/admin/wiki/${slug}`),
    createWiki: (data) => req('/admin/wiki', { method: 'POST', body: data }),
    updateWiki: (slug, data) => req(`/admin/wiki/${slug}`, { method: 'PUT', body: data }),
    publishWiki: (slug, published) =>
      req(`/admin/wiki/${slug}/publish`, { method: 'PATCH', body: { published } }),
    deleteWiki: (slug) => req(`/admin/wiki/${slug}`, { method: 'DELETE' }),
    listWikiRevisions: (slug) => req(`/admin/wiki/${slug}/revisions`),
    getWikiRevision: (slug, id) => req(`/admin/wiki/${slug}/revisions/${id}`),
    restoreWikiRevision: (slug, id) =>
      req(`/admin/wiki/${slug}/revisions/${id}/restore`, { method: 'POST' }),
    listWikiTags: () => req('/admin/wiki/tags'),
    listWikiCategories: () => req('/admin/wiki/categories'),
    createWikiCategory: (data) => req('/admin/wiki/categories', { method: 'POST', body: data }),
    updateWikiCategory: (id, data) =>
      req(`/admin/wiki/categories/${id}`, { method: 'PUT', body: data }),
    deleteWikiCategory: (id) => req(`/admin/wiki/categories/${id}`, { method: 'DELETE' }),
    getSettings: () => req('/admin/settings'),
    updateSettings: (obj) => req('/admin/settings', { method: 'PUT', body: obj }),
    activity: (limit = 50) => req(`/admin/activity?limit=${limit}`),
    botActivity: () => req('/admin/bot-activity'),
    unbanIp: (ip) => req('/admin/bot-activity/unban', { method: 'POST', body: { ip } }),
    listUsers: () => req('/admin/users'),
    createUser: (data) => req('/admin/users', { method: 'POST', body: data }),
    updateUser: (id, data) => req(`/admin/users/${id}`, { method: 'PUT', body: data }),
    deleteUser: (id) => req(`/admin/users/${id}`, { method: 'DELETE' }),

    // ----- account security (self-service 2FA) -----
    getAccount: () => req('/admin/account'),
    totpSetup: () => req('/admin/account/totp/setup', { method: 'POST' }),
    totpEnable: (code) => req('/admin/account/totp/enable', { method: 'POST', body: { code } }),
    totpDisable: (code) => req('/admin/account/totp/disable', { method: 'POST', body: { code } }),

    // ----- linked SSO identities (self-service) -----
    linkedIdentities: () => req('/admin/account/identities'),
    unlinkIdentity: (provider) => req(`/admin/account/identities/${provider}`, { method: 'DELETE' }),

    // ----- auth providers / SSO config (admin only) -----
    listAuthProviders: () => req('/admin/auth/providers'),
    createAuthProvider: (data) => req('/admin/auth/providers', { method: 'POST', body: data }),
    updateAuthProvider: (id, data) => req(`/admin/auth/providers/${id}`, { method: 'PUT', body: data }),
    deleteAuthProvider: (id) => req(`/admin/auth/providers/${id}`, { method: 'DELETE' }),

    // ----- Discord bot control (admin only) -----
    getDiscordBotConfig: () => req('/admin/discord-bot/config'),
    saveDiscordBotConfig: (data) => req('/admin/discord-bot/config', { method: 'PUT', body: data }),
  },
}

export { ApiError }
