// supabase-client.jsx — Supabase client + data access layer

const SUPABASE_URL  = "https://jhxcdnflugwwrnzjexpk.supabase.co";
const SUPABASE_ANON = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpoeGNkbmZsdWd3d3JuempleHBrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1NDAyMDMsImV4cCI6MjA5NDExNjIwM30.YlpdPStxnhKXZHJtWD8MFL_VgyJGosnJF_8Sgn6M4RY";

const sb = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON, {
  auth: { persistSession: true, autoRefreshToken: true },
});

// ── DB → App mappers ──────────────────────────────────────────

function dbToProfile(p) {
  p = p || {};
  return {
    name:          p.name          || "",
    initials:      p.initials      || "",
    email:         p.email         || "",
    phone:         p.phone         || "",
    brandName:     p.brand_name    || "",
    businessType:  p.business_type || "",
    setupComplete: p.setup_complete || false,
    logoText:      p.logo_text     || "N",
    logoUrl:       p.logo_url      || "",
    logoBg:        p.logo_bg       || "#efa403",
    logoColor:     p.logo_color    || "#ffffff",
    accent:        p.accent        || "#efa403",
    title:         p.title         || "",
    bio:           p.bio           || "",
    bookingUrl:    p.booking_url   || "",
    currency:      p.currency      || "GBP",
    theme:         p.theme         || "dark",
    whiteLabel:    p.white_label   || false,
    notifications: p.notifications || {},
    // company info
    vatNumber:     p.vat_number    || "",
    companyName:   p.company_name  || "",
    address1:      p.address1      || "",
    address2:      p.address2      || "",
    city:          p.city          || "",
    postcode:      p.postcode      || "",
    country:       p.country       || "GB",
    companyEmail:  p.company_email || "",
    companyPhone:  p.company_phone || "",
    website:       p.website       || "",
    whatsapp:      p.whatsapp      || "",
    facebook:      p.facebook      || "",
    instagram:     p.instagram_url || "",
    twitter:       p.twitter       || "",
    linkedin:      p.linkedin      || "",
    hideEmail:     p.hide_email      || false,
    hideAddress:   p.hide_address    || false,
    companyLat:    p.company_lat     || null,
    companyLon:    p.company_lon     || null,
    isSuperAdmin:  p.is_super_admin  || false,
    createdAt:     p.created_at      || null,
    plan:          p.plan            || "free",
    suspended:     p.suspended       || false,
  };
}

function dbToEvent(e) {
  return normalizeEvent({
    id:                    e.id,
    name:                  e.name,
    duration:              e.duration,
    slotInterval:          e.slot_interval,
    color:                 e.color,
    price:                 Number(e.price || 0),
    maxSpaces:             Number(e.max_spaces || 0),
    paymentMode:           e.payment_mode   || "none",
    depositAmount:         e.deposit_amount != null ? Number(e.deposit_amount) : "",
    termWeeks:             Number(e.term_weeks   || 0),
    classPrice:            Number(e.class_price  || 0),
    location:              e.location        || "",
    description:           e.description    || "",
    questions:             e.questions      || [],
    requireTerms:          e.require_terms  || false,
    termsText:             e.terms_text     || "",
    useCustomAvailability: e.use_custom_availability || false,
    customAvailability:    e.custom_availability     || [],
    enabled:               e.enabled !== false,
  });
}

function dbToAvailability(rows = []) {
  const DAYS = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
  const map = {};
  rows.forEach(r => { map[r.day_name] = r; });
  return DAYS.map(name => {
    const r = map[name] || {};
    return { name, on: r.enabled || false, start: r.start_time || "09:00", end: r.end_time || "17:00" };
  });
}

function dbToBooking(b) {
  return {
    id:              b.id,
    date:            b.date,
    time:            b.time,
    eventId:         b.event_id,
    eventName:       b.event_name,
    guestName:       b.guest_name,
    guestEmail:      b.guest_email,
    guestPhone:      b.guest_phone    || "",
    notes:           b.notes          || "",
    answers:         b.answers        || {},
    location:        b.location       || "",
    status:          b.status         || "Confirmed",
    paymentStatus:   b.payment_status,
    paymentProvider: b.payment_provider,
    paymentAmount:   b.payment_amount,
    source:          b.source         || "Public page",
    createdAt:       b.created_at,
    manageToken:     b.manage_token   || "",
    couponCode:      b.coupon_code    || "",
    discountApplied: Number(b.discount_applied || 0),
  };
}

function dbToBlockedTime(b) {
  return { id: b.id, date: b.date, start: b.start_time, end: b.end_time, reason: b.reason || "" };
}

// ── App → DB mappers ──────────────────────────────────────────

function profileToDb(p, userId) {
  return {
    id:             userId,
    name:           p.name          || null,
    initials:       p.initials      || null,
    email:          p.email         || null,
    phone:          p.phone         || null,
    brand_name:     p.brandName,
    business_type:  p.businessType,
    setup_complete: p.setupComplete,
    logo_text:      p.logoText,
    logo_url:       p.logoUrl       || null,
    logo_bg:        p.logoBg,
    logo_color:     p.logoColor,
    accent:         p.accent,
    title:          p.title,
    bio:            p.bio,
    booking_url:    p.bookingUrl,
    currency:       p.currency,
    theme:          p.theme,
    white_label:    p.whiteLabel    || false,
    notifications:  p.notifications || {},
    // company info
    vat_number:     p.vatNumber     || null,
    company_name:   p.companyName   || null,
    address1:       p.address1      || null,
    address2:       p.address2      || null,
    city:           p.city          || null,
    postcode:       p.postcode      || null,
    country:        p.country       || null,
    company_email:  p.companyEmail  || null,
    company_phone:  p.companyPhone  || null,
    website:        p.website       || null,
    whatsapp:       p.whatsapp      || null,
    facebook:       p.facebook      || null,
    instagram_url:  p.instagram     || null,
    twitter:        p.twitter       || null,
    linkedin:       p.linkedin      || null,
    hide_email:     p.hideEmail     || false,
    hide_address:   p.hideAddress   || false,
    company_lat:    p.companyLat    || null,
    company_lon:    p.companyLon    || null,
    updated_at:     new Date().toISOString(),
  };
}

function eventToDb(e, userId) {
  return {
    id:                      e.id,
    user_id:                 userId,
    name:                    e.name,
    duration:                Number(e.duration),
    slot_interval:           Number(e.slotInterval || e.duration),
    color:                   e.color,
    price:                   Number(e.price || 0),
    max_spaces:              Number(e.maxSpaces || 0),
    payment_mode:            e.paymentMode || "none",
    deposit_amount:          e.depositAmount === "" ? null : Number(e.depositAmount || 0),
    term_weeks:              Number(e.termWeeks   || 0),
    class_price:             Number(e.classPrice  || 0),
    location:                e.location    || "",
    description:             e.description || "",
    questions:               e.questions   || [],
    require_terms:           !!e.requireTerms,
    terms_text:              e.termsText   || "",
    use_custom_availability: !!e.useCustomAvailability,
    custom_availability:     e.customAvailability || [],
    enabled:                 e.enabled !== false,
  };
}

// ── Data fetchers ─────────────────────────────────────────────

async function fetchUserData(userId) {
  const [
    { data: profile },
    { data: events },
    { data: avail },
    { data: bookings },
    { data: bt },
    { data: activity },
  ] = await Promise.all([
    sb.from("profiles").select("*").eq("id", userId).single(),
    sb.from("events").select("*").eq("user_id", userId).order("created_at"),
    sb.from("availability").select("*").eq("user_id", userId),
    sb.from("bookings").select("*").eq("user_id", userId).order("created_at", { ascending: false }),
    sb.from("blocked_times").select("*").eq("user_id", userId),
    sb.from("activity").select("*").eq("user_id", userId).order("created_at", { ascending: false }).limit(8),
  ]);
  return {
    userId,
    profile:       dbToProfile(profile),
    events:        (events    || []).map(dbToEvent),
    availability:  dbToAvailability(avail),
    bookings:      (bookings  || []).map(dbToBooking),
    blockedTimes:  (bt        || []).map(dbToBlockedTime),
    blockedDates:  [],
    activity:      (activity  || []).map(a => ({ id: a.id, text: a.text, at: "Just now" })),
    integrations:  {},
    notifications: profile?.notifications || {},
    platform:      getInitialData().platform,
  };
}

async function fetchPublicData(slug) {
  const { data: profile, error } = await sb.from("profiles").select("*").eq("booking_url", slug).single();
  if (error || !profile) return null;
  const userId = profile.id;
  const [
    { data: events },
    { data: avail },
    { data: bookings },
    { data: bt },
  ] = await Promise.all([
    sb.from("events").select("*").eq("user_id", userId).eq("enabled", true).order("created_at"),
    sb.from("availability").select("*").eq("user_id", userId),
    sb.from("bookings").select("*").eq("user_id", userId),
    sb.from("blocked_times").select("*").eq("user_id", userId),
  ]);
  return {
    userId,
    profile:      dbToProfile(profile),
    events:       (events || []).map(dbToEvent),
    availability: dbToAvailability(avail),
    bookings:     (bookings || []).map(dbToBooking),
    blockedTimes: (bt || []).map(dbToBlockedTime),
    blockedDates: [],
    activity:     [],
    integrations: {},
    notifications: {},
    platform:     getInitialData().platform,
  };
}

async function fetchAllProfiles() {
  const [
    { data: profiles },
    { data: bookings },
    { data: events },
  ] = await Promise.all([
    sb.from("profiles").select("*").order("created_at", { ascending: false }),
    sb.from("bookings").select("user_id"),
    sb.from("events").select("user_id"),
  ]);
  const bookingCounts = {};
  const eventCounts   = {};
  (bookings || []).forEach(b => { bookingCounts[b.user_id] = (bookingCounts[b.user_id] || 0) + 1; });
  (events   || []).forEach(e => { eventCounts[e.user_id]   = (eventCounts[e.user_id]   || 0) + 1; });
  return (profiles || []).map(p => ({
    ...dbToProfile(p),
    id:           p.id,
    bookingCount: bookingCounts[p.id] || 0,
    eventCount:   eventCounts[p.id]   || 0,
    createdAt:    p.created_at,
  }));
}

async function fetchBookingByToken(token) {
  const { data: booking, error } = await sb.from("bookings").select("*").eq("manage_token", token).single();
  if (error || !booking) return null;
  const userId = booking.user_id;
  const [
    { data: profile },
    { data: events },
    { data: avail },
    { data: allBookings },
    { data: bt },
  ] = await Promise.all([
    sb.from("profiles").select("*").eq("id", userId).single(),
    sb.from("events").select("*").eq("user_id", userId).eq("enabled", true).order("created_at"),
    sb.from("availability").select("*").eq("user_id", userId),
    sb.from("bookings").select("*").eq("user_id", userId),
    sb.from("blocked_times").select("*").eq("user_id", userId),
  ]);
  return {
    booking: dbToBooking(booking),
    publicData: {
      userId,
      profile:      dbToProfile(profile || {}),
      events:       (events || []).map(dbToEvent),
      availability: dbToAvailability(avail),
      bookings:     (allBookings || []).map(dbToBooking),
      blockedTimes: (bt || []).map(dbToBlockedTime),
      blockedDates: [],
      activity: [], integrations: {}, notifications: {},
      platform: getInitialData().platform,
    },
  };
}

// ── Coupon validation ─────────────────────────────────────────

async function validateCoupon(code) {
  const today = new Date().toISOString().slice(0, 10);
  const { data, error } = await sb.from("coupons")
    .select("*")
    .eq("code", code.toUpperCase().trim())
    .eq("active", true)
    .or(`expires_at.is.null,expires_at.gte.${today}`)
    .single();
  if (error || !data) return { valid: false, error: "Coupon not found or has expired." };
  if (Number(data.max_uses) > 0 && Number(data.times_used) >= Number(data.max_uses))
    return { valid: false, error: "This coupon has reached its usage limit." };
  return {
    valid: true,
    coupon: {
      id:            data.id,
      code:          data.code,
      description:   data.description || "",
      discountType:  data.discount_type,
      discountValue: Number(data.discount_value || 0),
      trialDays:     Number(data.trial_days || 0),
      maxUses:       Number(data.max_uses || 0),
      timesUsed:     Number(data.times_used || 0),
    },
  };
}

async function incrementCouponUsage(couponId) {
  const { data: curr } = await sb.from("coupons").select("times_used").eq("id", couponId).single();
  if (curr) await sb.from("coupons").update({ times_used: (curr.times_used || 0) + 1 }).eq("id", couponId);
}

// ── Email notifications (Supabase Edge Function → Resend) ─────

async function sendBookingEmail(type, booking, profile) {
  try {
    await sb.functions.invoke("send-booking-email", { body: { type, booking, profile } });
  } catch (_) { /* silent — edge function may not be deployed yet */ }
}

// ── Platform admin fetchers ───────────────────────────────────

async function fetchCoupons() {
  const { data } = await sb.from("coupons").select("*").order("created_at", { ascending: false });
  return (data || []).map(c => ({
    id: c.id, code: c.code, description: c.description || "",
    discountType: c.discount_type || "percent",
    discountValue: c.discount_value != null ? Number(c.discount_value) : 0,
    trialDays: Number(c.trial_days || 0),
    maxUses: Number(c.max_uses || 0),
    timesUsed: Number(c.times_used || 0),
    active: c.active !== false,
    expiresAt: c.expires_at || "",
    createdAt: c.created_at,
  }));
}

async function saveCoupon(coupon) {
  const row = {
    id: coupon.id || uid("cpn"),
    code: coupon.code,
    description: coupon.description || "",
    discount_type: coupon.discountType,
    discount_value: coupon.discountType === "free" ? 0 : Number(coupon.discountValue || 0),
    trial_days: Number(coupon.trialDays || 0),
    max_uses: Number(coupon.maxUses || 0),
    times_used: Number(coupon.timesUsed || 0),
    active: coupon.active !== false,
    expires_at: coupon.expiresAt || null,
  };
  await sb.from("coupons").upsert(row);
  return row.id;
}

async function deleteCoupon(id) {
  await sb.from("coupons").delete().eq("id", id);
}

async function fetchAnnouncements() {
  const { data } = await sb.from("announcements").select("*").order("created_at", { ascending: false });
  return (data || []).map(a => ({
    id: a.id, title: a.title || "", message: a.message || "",
    type: a.type || "info",
    active: a.active !== false,
    expiresAt: a.expires_at || "",
    createdAt: a.created_at,
  }));
}

async function fetchActiveAnnouncements() {
  const today = new Date().toISOString().slice(0, 10);
  const { data } = await sb.from("announcements").select("*")
    .eq("active", true)
    .or(`expires_at.is.null,expires_at.gte.${today}`)
    .order("created_at", { ascending: false });
  return (data || []).map(a => ({
    id: a.id, title: a.title || "", message: a.message || "", type: a.type || "info",
  }));
}

async function saveAnnouncement(ann) {
  const row = {
    id: ann.id || uid("ann"),
    title: ann.title || "",
    message: ann.message || "",
    type: ann.type || "info",
    active: ann.active !== false,
    expires_at: ann.expiresAt || null,
  };
  await sb.from("announcements").upsert(row);
  return row.id;
}

async function deleteAnnouncement(id) {
  await sb.from("announcements").delete().eq("id", id);
}

async function fetchPlatformNotes(profileId) {
  const { data } = await sb.from("platform_notes").select("*").eq("profile_id", profileId).order("created_at", { ascending: false });
  return (data || []).map(n => ({ id: n.id, note: n.note || "", createdAt: n.created_at }));
}

async function addPlatformNote(profileId, note) {
  const row = { id: uid("note"), profile_id: profileId, note };
  await sb.from("platform_notes").insert(row);
  return row;
}

async function fetchPlatformActivity() {
  const { data } = await sb.from("activity").select("*").order("created_at", { ascending: false }).limit(100);
  return (data || []).map(a => ({ id: a.id, userId: a.user_id, text: a.text, createdAt: a.created_at }));
}

async function updateAccountPlan(userId, plan) {
  await sb.from("profiles").update({ plan }).eq("id", userId);
}

async function updateAccountSuspended(userId, suspended) {
  await sb.from("profiles").update({ suspended }).eq("id", userId);
}

// expose globally (used by app-state + booking page)
window.sb               = sb;
window.fetchUserData    = fetchUserData;
window.fetchPublicData  = fetchPublicData;
window.profileToDb      = profileToDb;
window.eventToDb        = eventToDb;
window.dbToBooking      = dbToBooking;
window.dbToEvent        = dbToEvent;
window.dbToAvailability      = dbToAvailability;
window.fetchBookingByToken   = fetchBookingByToken;
window.fetchAllProfiles      = fetchAllProfiles;
window.validateCoupon        = validateCoupon;
window.incrementCouponUsage  = incrementCouponUsage;
window.sendBookingEmail      = sendBookingEmail;
window.fetchCoupons          = fetchCoupons;
window.saveCoupon            = saveCoupon;
window.deleteCoupon          = deleteCoupon;
window.fetchAnnouncements    = fetchAnnouncements;
window.fetchActiveAnnouncements = fetchActiveAnnouncements;
window.saveAnnouncement      = saveAnnouncement;
window.deleteAnnouncement    = deleteAnnouncement;
window.fetchPlatformNotes    = fetchPlatformNotes;
window.addPlatformNote       = addPlatformNote;
window.fetchPlatformActivity = fetchPlatformActivity;
window.updateAccountPlan     = updateAccountPlan;
window.updateAccountSuspended = updateAccountSuspended;
