// supabase.jsx — Supabase client + helpers (auth, reports, storage, realtime)
//
// ⚠️  ขั้นตอนที่ต้องทำหลังสร้าง project ที่ supabase.com:
//     1. แทน YOUR_PROJECT_ID ด้วย Project URL  (Settings → API → URL)
//     2. แทน YOUR_ANON_KEY   ด้วย anon / public key  (Settings → API → Project API keys)
//     3. รัน schema.sql ใน SQL Editor ของ Supabase

const SUPABASE_URL      = 'https://bbyfaivzfmckucasecqh.supabase.co';
const SUPABASE_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJieWZhaXZ6Zm1ja3VjYXNlY3FoIiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODAyMzcwODAsImV4cCI6MjA5NTgxMzA4MH0.Ea9pSX3L0_tOsFXinoZdibyvTc98N1_6T5EpBblwUSs';

const SB_CONFIGURED = !SUPABASE_URL.includes('YOUR_PROJECT_ID');

const _sb = SB_CONFIGURED
  ? window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY)
  : null;

// ─── Helpers ─────────────────────────────────────────────────
function toEmail(identifier) {
  const v = (identifier || '').trim().toLowerCase();
  if (v.includes('@')) return v;
  // Build ASCII-safe stable local part: ASCII letters/digits/._- kept, others → x<hex codepoint>
  let out = '';
  for (const ch of v) {
    if (/[a-z0-9._-]/.test(ch)) out += ch;
    else out += 'x' + ch.codePointAt(0).toString(16).padStart(4, '0');
  }
  // Ensure starts with a letter (Supabase rejects emails starting with digit)
  if (!/^[a-z]/.test(out)) out = 'u' + out;
  return `${out}@bodinplus.local`;
}

// ─── Auth ─────────────────────────────────────────────────────
async function sbSignIn(identifier, password) {
  if (!SB_CONFIGURED) throw new Error('not_configured');
  const { data, error } = await _sb.auth.signInWithPassword({
    email: toEmail(identifier), password,
  });
  if (error) throw error;
  const { data: profile } = await _sb.from('profiles')
    .select('*').eq('id', data.user.id).single();
  return { user: data.user, profile };
}

async function sbSignOut() {
  if (_sb) await _sb.auth.signOut();
}

async function sbGetSession() {
  if (!_sb) return null;
  const { data: { session } } = await _sb.auth.getSession();
  if (!session) return null;
  const { data: profile } = await _sb.from('profiles')
    .select('*').eq('id', session.user.id).single();
  return { user: session.user, profile };
}

async function sbUpdateAvatar(dataUrl) {
  if (!SB_CONFIGURED) throw new Error('not_configured');
  const { data: { user } } = await _sb.auth.getUser();
  if (!user) throw new Error('not_logged_in');
  const { error } = await _sb.from('profiles')
    .update({ avatar_url: dataUrl }).eq('id', user.id);
  if (error) throw error;
}

async function sbUpdateDisplayName(newName) {
  if (!SB_CONFIGURED) throw new Error('not_configured');
  const { data: { user } } = await _sb.auth.getUser();
  if (!user) throw new Error('not_logged_in');
  const { error } = await _sb.from('profiles')
    .update({ display_name: newName }).eq('id', user.id);
  if (error) throw error;
}

async function sbUpdateUsername(currentPassword, newUsername) {
  if (!SB_CONFIGURED) throw new Error('not_configured');
  const { data: { user } } = await _sb.auth.getUser();
  if (!user) throw new Error('not_logged_in');
  // Re-auth with current password
  const { error: signInError } = await _sb.auth.signInWithPassword({
    email: user.email, password: currentPassword,
  });
  if (signInError) throw new Error('wrong_current_password');
  // Update auth email + profile.student_id
  const newEmail = toEmail(newUsername);
  const { error: emailError } = await _sb.auth.updateUser({ email: newEmail });
  if (emailError) throw emailError;
  const { error: profErr } = await _sb.from('profiles')
    .update({ student_id: newUsername }).eq('id', user.id);
  if (profErr) throw profErr;
}

async function sbUpdatePassword(currentPassword, newPassword) {
  if (!SB_CONFIGURED) throw new Error('not_configured');
  // Re-authenticate first to verify current password
  const { data: { user } } = await _sb.auth.getUser();
  if (!user) throw new Error('not_logged_in');
  const { error: signInError } = await _sb.auth.signInWithPassword({
    email: user.email, password: currentPassword,
  });
  if (signInError) throw new Error('wrong_current_password');
  const { error } = await _sb.auth.updateUser({ password: newPassword });
  if (error) throw error;
}

async function sbSignUp(identifier, password, meta) {
  if (!SB_CONFIGURED) throw new Error('not_configured');
  const { data, error } = await _sb.auth.signUp({
    email: toEmail(identifier), password,
  });
  if (error) throw error;
  await _sb.from('profiles').upsert({
    id: data.user.id,
    display_name: meta.name,
    role: meta.role || 'student',
    grade: meta.grade || null,
    student_id: identifier,
  });
  const { data: profile } = await _sb.from('profiles')
    .select('*').eq('id', data.user.id).single();
  return { user: data.user, profile };
}

// ─── Row ↔ Report mapping ────────────────────────────────────
function rowToReport(row) {
  return {
    id:          row.id,
    category:    row.category,
    title:       row.title || '',
    titleEn:     row.title_en || '',
    desc:        row.description || '',
    descEn:      row.desc_en || '',
    location:    row.location || '',
    locationEn:  row.location_en || '',
    reporter:    row.reporter_name || '',
    grade:       row.grade || '',
    submittedAt: row.submitted_at,
    urgency:     row.urgency || 'normal',
    status:      row.status || 'pending',
    progress:    row.progress || 0,
    before: row.before_label
      ? { label: row.before_label, hue: row.before_hue || 270, url: row.before_url || null }
      : null,
    after: row.after_label
      ? { label: row.after_label, hue: row.after_hue || 155, url: row.after_url || null }
      : null,
    timeline:    row.timeline || [],
    thanks:      row.thanks || 0,
    reporter_id: row.reporter_id || null,
  };
}

function reportToRow(r) {
  return {
    id:            r.id,
    category:      r.category,
    title:         r.title || '',
    title_en:      r.titleEn || '',
    description:   r.desc || '',
    desc_en:       r.descEn || '',
    location:      r.location || '',
    location_en:   r.locationEn || '',
    reporter_id:   r.reporter_id || null,
    reporter_name: r.reporter || '',
    grade:         r.grade || '',
    submitted_at:  r.submittedAt,
    urgency:       r.urgency || 'normal',
    status:        r.status || 'pending',
    progress:      r.progress || 0,
    before_label:  r.before?.label || null,
    before_hue:    r.before?.hue  || null,
    before_url:    r.before?.url  || null,
    after_label:   r.after?.label  || null,
    after_hue:     r.after?.hue   || null,
    after_url:     r.after?.url   || null,
    timeline:      r.timeline || [],
    thanks:        r.thanks || 0,
  };
}

// ─── Reports CRUD ─────────────────────────────────────────────
async function sbFetchReports() {
  if (!_sb) return null;
  const { data, error } = await _sb
    .from('reports')
    .select('*')
    .order('submitted_at', { ascending: false });
  if (error) throw error;
  return (data || []).map(rowToReport);
}

async function sbInsertReport(report) {
  if (!_sb) return report;
  const { data, error } = await _sb
    .from('reports').insert(reportToRow(report)).select().single();
  if (error) throw error;
  return rowToReport(data);
}

async function sbUpdateReport(id, updated) {
  if (!_sb) return updated;
  const { data, error } = await _sb
    .from('reports').update(reportToRow(updated)).eq('id', id).select().single();
  if (error) throw error;
  return rowToReport(data);
}

// ─── Storage (ภาพก่อน/หลัง) ──────────────────────────────────
async function sbUploadImage(file, reportId, type) {
  if (!_sb) return null;
  const ext = (file.name || '').split('.').pop() || 'jpg';
  const path = `${reportId}/${type}.${ext}`;
  const { error } = await _sb.storage
    .from('report-images').upload(path, file, { upsert: true });
  if (error) throw error;
  const { data } = _sb.storage.from('report-images').getPublicUrl(path);
  return data.publicUrl;
}

// ─── Realtime ─────────────────────────────────────────────────
function sbSubscribeReports(onInsert, onUpdate) {
  if (!_sb) return null;
  return _sb.channel('reports-live')
    .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'reports' },
      ({ new: row }) => onInsert(rowToReport(row)))
    .on('postgres_changes', { event: 'UPDATE', schema: 'public', table: 'reports' },
      ({ new: row }) => onUpdate(rowToReport(row)))
    .subscribe();
}

function sbUnsubscribe(channel) {
  if (_sb && channel) _sb.removeChannel(channel);
}
