// upload.jsx — talks to dashboard.gravida.nl's public scan endpoints.
//
// Three steps, all routed through a shared `gravidaUpload` helper on `window`:
//
//   1) await gravidaUpload.init({ first_name, last_name, email, ... })
//        → returns { sessionId }
//   2) await gravidaUpload.photo(sessionId, file, { angle, order_idx, note })
//        → returns { url }
//   3) await gravidaUpload.complete(sessionId, { email, first_name, ... })
//        → returns { status: 'received' }
//
// Endpoints + app token are read from window.GRAVIDA_API_CONFIG, which
// index.html sets before any JSX loads. Override there per environment.

const DEFAULT_BASE  = 'https://dashboard.gravida.nl'
const DEFAULT_TOKEN = ''   // empty in dev; production injects via index.html

function cfg() {
  const c = (typeof window !== 'undefined' && window.GRAVIDA_API_CONFIG) || {}
  return {
    base:  (c.base  || DEFAULT_BASE).replace(/\/$/, ''),
    token: c.token  || DEFAULT_TOKEN,
  }
}

function headersJson() {
  const { token } = cfg()
  const h = { 'Content-Type': 'application/json' }
  if (token) h['X-Scan-App-Token'] = token
  return h
}

function headersMultipart() {
  const { token } = cfg()
  const h = {}
  if (token) h['X-Scan-App-Token'] = token
  return h
}

async function init(opts) {
  const { base } = cfg()
  const res = await fetch(`${base}/api/scan/upload-init`, {
    method: 'POST',
    headers: headersJson(),
    body: JSON.stringify({
      first_name:         opts && opts.first_name        || null,
      last_name:          opts && opts.last_name         || null,
      email:              opts && opts.email             || null,
      phone:              opts && opts.phone             || null,
      pregnancy_weeks:    opts && opts.pregnancy_weeks   || null,
      consent_eu_storage: opts ? opts.consent_eu_storage !== false : true,
      scan_mode:          opts && opts.scan_mode          || 'standing',
      app_version:        '1.0.0',
      device_label:       (typeof navigator !== 'undefined' && navigator.userAgent) || null,
    }),
  })
  if (!res.ok) throw new Error(`init failed (${res.status})`)
  const data = await res.json()
  return { sessionId: data.session_id }
}

// Convert a captured blob/dataURL/File into a File the multipart endpoint accepts.
function toFile(input, fallbackName) {
  if (input instanceof File) return input
  if (input instanceof Blob) return new File([input], fallbackName || 'photo.jpg', { type: input.type || 'image/jpeg' })
  if (typeof input === 'string' && input.startsWith('data:')) {
    const [head, b64] = input.split(',')
    const mime = (/data:([^;]+);/.exec(head) || [])[1] || 'image/jpeg'
    const bin  = atob(b64)
    const buf  = new Uint8Array(bin.length)
    for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i)
    return new File([buf], fallbackName || 'photo.jpg', { type: mime })
  }
  throw new Error('Unsupported photo input')
}

async function photo(sessionId, input, { angle, order_idx = 0, location_idx = 0, note } = {}) {
  const { base } = cfg()
  const locTag = location_idx > 0 ? `-loc${location_idx}` : ''
  const file = toFile(input, `${angle}${locTag}-${order_idx}.jpg`)
  const fd = new FormData()
  fd.append('file', file)
  fd.append('angle', angle)
  fd.append('order_idx', String(order_idx))
  fd.append('location_idx', String(location_idx))
  if (note) fd.append('note', note)

  const res = await fetch(`${base}/api/scan/${encodeURIComponent(sessionId)}/photo`, {
    method: 'POST',
    headers: headersMultipart(),
    body: fd,
  })
  if (!res.ok) {
    let msg = `photo upload failed (${res.status})`
    try { const j = await res.json(); if (j && j.error) msg = j.error } catch {}
    throw new Error(msg)
  }
  return res.json()
}

async function complete(sessionId, opts) {
  const { base } = cfg()
  const res = await fetch(`${base}/api/scan/${encodeURIComponent(sessionId)}/complete`, {
    method: 'POST',
    headers: headersJson(),
    body: JSON.stringify({
      first_name:      opts && opts.first_name      || null,
      last_name:       opts && opts.last_name       || null,
      email:           opts && opts.email,
      phone:           opts && opts.phone           || null,
      pregnancy_weeks: opts && opts.pregnancy_weeks || null,
      scan_mode:       opts && opts.scan_mode       || null,
    }),
  })
  if (!res.ok) {
    let msg = `complete failed (${res.status})`
    try { const j = await res.json(); if (j && j.error) msg = j.error } catch {}
    throw new Error(msg)
  }
  return res.json()
}

// Public surface.
window.gravidaUpload = { init, photo, complete };
