// db.jsx — Supabase client + helper functions for swaps, players, teams.
// All functions return Promises and throw on error. Caller handles UI.

const PJ_CFG = window.POKER_JAMIE_CONFIG || {};
const PJ_DB_READY = (
  PJ_CFG.supabaseUrl &&
  PJ_CFG.supabaseUrl !== '__INJECT__' &&
  PJ_CFG.supabaseAnonKey &&
  PJ_CFG.supabaseAnonKey !== '__INJECT__' &&
  typeof window.supabase !== 'undefined'
);

window.pjDB = PJ_DB_READY
  ? window.supabase.createClient(PJ_CFG.supabaseUrl, PJ_CFG.supabaseAnonKey)
  : null;

window.pjDBReady = PJ_DB_READY;

// ---- Device identity (localStorage UUID) -----------------------------------
function pjUuid() {
  // RFC4122 v4-ish (browser-safe)
  if (window.crypto && window.crypto.randomUUID) return window.crypto.randomUUID();
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

window.pjDeviceId = (function () {
  let id = null;
  try { id = window.localStorage.getItem('pj_device_id'); } catch (_) {}
  if (!id) {
    id = pjUuid();
    try { window.localStorage.setItem('pj_device_id', id); } catch (_) {}
  }
  return id;
})();

window.pjGetHandle = () => {
  try { return window.localStorage.getItem('pj_handle') || ''; } catch (_) { return ''; }
};
window.pjSetHandle = (h) => {
  try { window.localStorage.setItem('pj_handle', h || ''); } catch (_) {}
};

// ---- Signature capture -----------------------------------------------------
window.pjCaptureSignature = async function (handle) {
  const sig = {
    handle: (handle || '').trim(),
    signed_at: new Date().toISOString(),
    device_id: window.pjDeviceId,
    user_agent: navigator.userAgent || '',
    gps: null
  };
  // GPS is best-effort; never block
  try {
    if (navigator.geolocation) {
      sig.gps = await new Promise((resolve) => {
        const t = setTimeout(() => resolve(null), 4000);
        navigator.geolocation.getCurrentPosition(
          (pos) => {
            clearTimeout(t);
            resolve({
              lat: pos.coords.latitude,
              lng: pos.coords.longitude,
              accuracy: pos.coords.accuracy
            });
          },
          () => { clearTimeout(t); resolve(null); },
          { enableHighAccuracy: false, timeout: 4000, maximumAge: 60000 }
        );
      });
    }
  } catch (_) { /* ignore */ }
  return sig;
};

// ---- DB helpers ------------------------------------------------------------
function pjRequireDB() {
  if (!window.pjDB) {
    throw new Error('Database not configured yet. Try again in a moment.');
  }
}

window.pjCreateSwap = async function (payload) {
  pjRequireDB();
  const secret_token = pjUuid().replace(/-/g, '');
  const row = {
    tournament_name: payload.tournament_name,
    buy_in: payload.buy_in,
    originator_handle: payload.originator_handle,
    originator_pct: payload.originator_pct,
    acceptor_pct: payload.acceptor_pct,
    markup: payload.markup,
    terms: payload.terms || [],
    notes: payload.notes || '',
    status: 'pending',
    originator_device_id: window.pjDeviceId,
    secret_token
  };
  const { data, error } = await window.pjDB.from('swaps').insert(row).select().single();
  if (error) throw error;
  return data;
};

window.pjGetSwap = async function (id) {
  pjRequireDB();
  const { data, error } = await window.pjDB.from('swaps').select('*').eq('id', id).single();
  if (error) throw error;
  return data;
};

window.pjAcceptorSign = async function (id, acceptorHandle, secretToken) {
  pjRequireDB();
  const sig = await window.pjCaptureSignature(acceptorHandle);
  const { data, error } = await window.pjDB
    .from('swaps')
    .update({
      acceptor_handle: acceptorHandle,
      acceptor_signature: sig,
      accepted_at: new Date().toISOString(),
      status: 'pending'
    })
    .eq('id', id)
    .eq('secret_token', secretToken)
    .select()
    .single();
  if (error) throw error;
  return data;
};

window.pjFinalLock = async function (id) {
  pjRequireDB();
  const swap = await window.pjGetSwap(id);
  const sig = await window.pjCaptureSignature(swap.originator_handle);
  const { data, error } = await window.pjDB
    .from('swaps')
    .update({
      originator_signature: sig,
      locked_at: new Date().toISOString(),
      status: 'locked'
    })
    .eq('id', id)
    .select()
    .single();
  if (error) throw error;
  return data;
};

window.pjListMySwaps = async function () {
  pjRequireDB();
  const handle = window.pjGetHandle();
  const device = window.pjDeviceId;
  // Match by device id OR handle (originator or acceptor)
  const orParts = [`originator_device_id.eq.${device}`];
  if (handle) {
    orParts.push(`originator_handle.eq.${handle}`);
    orParts.push(`acceptor_handle.eq.${handle}`);
  }
  const { data, error } = await window.pjDB
    .from('swaps')
    .select('*')
    .or(orParts.join(','))
    .order('created_at', { ascending: false });
  if (error) throw error;
  return data || [];
};

window.pjListMyOpponents = async function () {
  const swaps = await window.pjListMySwaps();
  const me = (window.pjGetHandle() || '').toLowerCase();
  const myDevice = window.pjDeviceId;
  const byHandle = new Map();
  for (const s of swaps) {
    const isMineAsOrig = s.originator_device_id === myDevice
      || (me && (s.originator_handle || '').toLowerCase() === me);
    const oppHandle = isMineAsOrig ? s.acceptor_handle : s.originator_handle;
    if (!oppHandle) continue;
    const key = oppHandle.toLowerCase();
    if (!byHandle.has(key)) {
      byHandle.set(key, {
        handle: oppHandle,
        count: 0,
        lastAt: null,
        volume: 0
      });
    }
    const rec = byHandle.get(key);
    rec.count += 1;
    const stamp = s.locked_at || s.accepted_at || s.created_at;
    if (stamp && (!rec.lastAt || stamp > rec.lastAt)) rec.lastAt = stamp;
    const myPct = isMineAsOrig ? (s.originator_pct || 0) : (s.acceptor_pct || 0);
    rec.volume += (Number(s.buy_in) || 0) * (Number(myPct) || 0) / 100;
  }
  return Array.from(byHandle.values()).sort((a, b) => (b.lastAt || '').localeCompare(a.lastAt || ''));
};

window.pjSubscribeSwap = function (id, onChange) {
  if (!window.pjDB) return () => {};
  const ch = window.pjDB
    .channel('swap-' + id)
    .on('postgres_changes',
      { event: 'UPDATE', schema: 'public', table: 'swaps', filter: 'id=eq.' + id },
      (payload) => onChange(payload.new))
    .subscribe();
  return () => { try { window.pjDB.removeChannel(ch); } catch (_) {} };
};
