// api.jsx — front-end client for the Ortho Care backend.
// When the server is reachable the app runs as a real multi-user system;
// when it is not (e.g. opened straight from disk), the app falls back to the
// in-memory seed data so the prototype still demonstrates every screen.

const API_BASE = (function () {
  // Same-origin when served by the Node server; explicit localhost otherwise.
  if (location.protocol === 'http:' || location.protocol === 'https:') return '';
  return 'http://localhost:3000';
})();

const TOKEN_KEY = 'ortho_token';

const API = {
  base: API_BASE,
  available: false,
  token: null,
  dailyToken: null,

  _headers(json = true) {
    const h = {};
    if (json) h['Content-Type'] = 'application/json';
    if (this.token) h['Authorization'] = 'Bearer ' + this.token;
    return h;
  },

  async _req(method, path, body, raw) {
    const opts = { method, headers: this._headers(!raw && body !== undefined) };
    if (body !== undefined) opts.body = raw ? body : JSON.stringify(body);
    const res = await fetch(this.base + '/api' + path, opts);
    let data = null;
    try { data = await res.json(); } catch (e) {}
    if (!res.ok) throw Object.assign(new Error((data && data.error) || res.statusText), { status: res.status, data });
    return data;
  },

  // ── lifecycle ──
  async init() {
    try {
      const ctrl = new AbortController();
      const t = setTimeout(() => ctrl.abort(), 1500);
      const res = await fetch(this.base + '/api/health', { signal: ctrl.signal });
      clearTimeout(t);
      if (!res.ok) throw new Error('health');
      this.available = true;
      this.token = localStorage.getItem(TOKEN_KEY) || null;
      const daily = await this._req('GET', '/daily/current');
      this.dailyToken = daily.token;
      this.daily = daily;
      return true;
    } catch (e) {
      this.available = false;
      return false;
    }
  },

  // ── auth ──
  async login(id, password) {
    const data = await this._req('POST', '/auth/login', { id, password });
    this.token = data.token;
    try { localStorage.setItem(TOKEN_KEY, data.token); } catch (e) {}
    return data.account;
  },
  logout() {
    this.token = null;
    try { localStorage.removeItem(TOKEN_KEY); } catch (e) {}
  },
  async me() {
    if (!this.token) return null;
    try { return (await this._req('GET', '/auth/me')).account; }
    catch (e) { this.logout(); return null; }
  },

  // ── patient surface ──
  checkPhone(phone) { return this._req('POST', `/s/${this.dailyToken}/check-phone`, { phone }); },

  async uploadFile(file) {
    const kind = file.type.startsWith('image') ? 'image' : file.type.startsWith('video') ? 'video' : 'pdf';
    const q = `?name=${encodeURIComponent(file.name)}&mime=${encodeURIComponent(file.type || 'application/octet-stream')}&type=${kind}`;
    const res = await fetch(this.base + `/api/s/${this.dailyToken}/uploads` + q, {
      method: 'POST', headers: { 'Content-Type': 'application/octet-stream' }, body: file,
    });
    if (!res.ok) throw new Error('upload_failed');
    return res.json(); // { type, name, url, key, size }
  },

  createSubmission(payload) { return this._req('POST', `/s/${this.dailyToken}/submissions`, payload); },

  // patient self-service: look up & edit their own submission (keyed by phone, within 24h)
  async mySubmission(phone) {
    try { return await this._req('POST', `/s/${this.dailyToken}/my-submission`, { phone }); }
    catch (e) { if (e.status === 404) return { none: true }; throw e; }
  },
  updateSubmission(id, payload) { return this._req('PUT', `/s/${this.dailyToken}/submissions/${id}`, payload); },

  // ── staff queue ──
  async getSubmissions(day = 'today') {
    const d = await this._req('GET', `/submissions?day=${day}`);
    return d.submissions;
  },
  setSeen(id, seen) { return this._req('PATCH', `/submissions/${id}/seen`, { seen }); },
  deleteSubmission(id) { return this._req('DELETE', `/submissions/${id}`); },

  // ── admin ──
  async getAccounts() { return (await this._req('GET', '/accounts')).accounts; },
  async createAccount(acc) { return (await this._req('POST', '/accounts', acc)).account; },
  deleteAccount(id) { return this._req('DELETE', `/accounts/${id}`); },

  // ── realtime ──
  subscribe(handlers) {
    if (!this.available || typeof EventSource === 'undefined') return () => {};
    const es = new EventSource(this.base + '/api/events');
    const on = (name) => es.addEventListener(name, (e) => {
      let data = {}; try { data = JSON.parse(e.data); } catch (err) {}
      handlers[name] && handlers[name](data);
    });
    ['submission', 'seen', 'delete'].forEach(on);
    return () => es.close();
  },
};

window.API = API;
