// Unified ERPNext API helper for all modules
import { BASE_URL } from 'src/config/erpnext'
import { authFetch } from './auth'

// List documents with filters, fields, pagination
export async function listDocs (doctype, { filters = {}, or_filters, fields = ['name'], limit = 20, offset = 0, orderBy = 'creation desc' } = {}) {
  const params = new URLSearchParams({
    fields: JSON.stringify(fields),
    filters: JSON.stringify(filters),
    limit_page_length: limit,
    limit_start: offset,
    order_by: orderBy,
  })
  if (or_filters) params.set('or_filters', JSON.stringify(or_filters))
  const res = await authFetch(BASE_URL + '/api/resource/' + encodeURIComponent(doctype) + '?' + params)
  if (!res.ok) throw new Error('API error: ' + res.status)
  const data = await res.json()
  return data.data || []
}

// Get single document
export async function getDoc (doctype, name) {
  const res = await authFetch(BASE_URL + '/api/resource/' + encodeURIComponent(doctype) + '/' + encodeURIComponent(name))
  if (!res.ok) throw new Error('Not found: ' + name)
  const data = await res.json()
  return data.data
}

// Search (for autocomplete / search bars)
export async function searchDocs (doctype, text, { filters = {}, fields = ['name'], limit = 20 } = {}) {
  const params = new URLSearchParams({
    doctype,
    txt: text,
    filters: JSON.stringify(filters),
    limit_page_length: limit,
  })
  const res = await authFetch(BASE_URL + '/api/method/frappe.client.get_list?' + params)
  if (!res.ok) return []
  const data = await res.json()
  return data.message || []
}

// Create a new document
export async function createDoc (doctype, data) {
  const res = await authFetch(BASE_URL + '/api/resource/' + encodeURIComponent(doctype), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  })
  const json = await res.json()
  if (!res.ok) {
    const msg = json?.exception?.split('\n')[0] || json?.message || ('Create failed: ' + res.status)
    throw new Error(msg)
  }
  return json.data
}

// Update a document (partial update)
export async function updateDoc (doctype, name, data) {
  const url = BASE_URL + '/api/resource/' + encodeURIComponent(doctype) + '/' + encodeURIComponent(name)
  const res = await authFetch(url, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  })
  if (!res.ok) throw new Error('Update failed: ' + res.status)
  const json = await res.json()
  return json.data
}

// Delete a document
export async function deleteDoc (doctype, name) {
  const url = BASE_URL + '/api/resource/' + encodeURIComponent(doctype) + '/' + encodeURIComponent(name)
  const res = await authFetch(url, { method: 'DELETE' })
  if (!res.ok) {
    let msg = 'Delete failed: ' + res.status
    try {
      const json = await res.json()
      msg = json?.exception?.split('\n')[0] || json?._server_messages || json?.message || msg
    } catch (_) {}
    throw new Error(msg)
  }
  return true
}

// Count documents. ⚠️ frappe.client.get_count IGNORE or_filters (recherche OR) → il renverrait un compte
// faux (souvent 0) dès qu'on cherche. Quand or_filters est présent, on compte via get_list (fields=name,
// sans limite) — les jeux de recherche sont bornés par le terme tapé. Sinon (chips seuls) : get_count rapide.
export async function countDocs (doctype, filters = {}, or_filters) {
  if (or_filters && or_filters.length) {
    const p = new URLSearchParams({
      doctype,
      filters: JSON.stringify(filters),
      or_filters: JSON.stringify(or_filters),
      fields: JSON.stringify(['name']),
      limit_page_length: '0',
    })
    const r = await authFetch(BASE_URL + '/api/method/frappe.client.get_list?' + p)
    if (!r.ok) return 0
    const d = await r.json()
    return ((d.message || d.data) || []).length
  }
  const params = new URLSearchParams({ doctype, filters: JSON.stringify(filters) })
  const res = await authFetch(BASE_URL + '/api/method/frappe.client.get_count?' + params)
  if (!res.ok) return 0
  const data = await res.json()
  return data.message || 0
}
