/* ============================================================
   Carzello — Firebase bridge (project: carzello-app)
   - Real authentication (email/password via Firebase Auth)
   - Per-user cloud state: states/{uid} when signed in,
     states/{deviceId} for signed-out browsing (local-first)
   - Shared inventory: platform/inventory doc — written by admin
     accounts, read by every visitor, so team-added cars are
     visible to everyone.
   ============================================================ */

const FIREBASE_CONFIG = {
  apiKey: "AIzaSyArrlP_-ZeL0ZcQP3VgkDB50uHrrITugWE",
  authDomain: "carzello-app.firebaseapp.com",
  projectId: "carzello-app",
  messagingSenderId: "848051840183",
  appId: "1:848051840183:web:03e8752c9e18c8c03a9932",
};

/* Accounts allowed into the operator console + shared-inventory writes.
   Must match the allowlist in /firestore.rules. */
const ADMIN_EMAILS = ["support@sayarah.io", "obaidullah.didar3@gmail.com"];

const LS_STATE_KEY = "sayarah.clear.v1";       // engine persistence (legacy name kept)
const LS_SHARED_INV = "carzello.sharedinv";    // cached copy of platform/inventory

const FB = (() => {
  let db = null, auth = null, deviceId = null, saveTimer = null, invTimer = null;
  const listeners = new Set();
  try {
    if (typeof firebase !== "undefined") {
      firebase.initializeApp(FIREBASE_CONFIG);
      db = firebase.firestore();
      // WebChannel streaming is blocked on some networks/proxies → Listen requests 503-loop.
      // Auto-detected long-polling falls back transparently where needed.
      db.settings({ experimentalAutoDetectLongPolling: true, merge: true });
      auth = firebase.auth();
      deviceId = localStorage.getItem("carzello.device");
      if (!deviceId) { deviceId = crypto.randomUUID(); localStorage.setItem("carzello.device", deviceId); }
    }
  } catch (e) { console.warn("Firebase unavailable — running local-only.", e); db = null; auth = null; }

  const stateDoc = () => db.collection("states").doc(auth && auth.currentUser ? auth.currentUser.uid : deviceId);
  const invDoc = () => db.collection("platform").doc("inventory");

  if (auth) {
    auth.onAuthStateChanged((u) => { listeners.forEach((fn) => { try { fn(u); } catch (e) {} }); });
  }

  const explain = (e) => {
    const c = (e && e.code) || "";
    if (c.includes("configuration-not-found") || c.includes("operation-not-allowed"))
      return "Sign-in is being activated for Carzello — please try again shortly.";
    if (c.includes("invalid-credential") || c.includes("wrong-password") || c.includes("user-not-found"))
      return "Wrong email or password.";
    if (c.includes("email-already-in-use")) return "An account with this email already exists — sign in instead.";
    if (c.includes("weak-password")) return "Password must be at least 6 characters.";
    if (c.includes("invalid-email")) return "That email address doesn't look right.";
    if (c.includes("too-many-requests")) return "Too many attempts — wait a minute and try again.";
    return (e && e.message) || "Something went wrong. Try again.";
  };

  return {
    enabled: !!db,
    deviceId,
    ADMIN_EMAILS,

    /* ---- auth ---- */
    currentUser() { return auth ? auth.currentUser : null; },
    isAdmin(u) { const usr = u || (auth && auth.currentUser); return !!(usr && usr.email && ADMIN_EMAILS.includes(usr.email.toLowerCase())); },
    onAuth(fn) { listeners.add(fn); if (auth) fn(auth.currentUser); return () => listeners.delete(fn); },
    signIn(email, pw) { return auth.signInWithEmailAndPassword(email.trim(), pw).catch((e) => { throw new Error(explain(e)); }); },
    signUp(email, pw, name) {
      return auth.createUserWithEmailAndPassword(email.trim(), pw)
        .then((cred) => (name ? cred.user.updateProfile({ displayName: name }).then(() => cred) : cred))
        .catch((e) => { throw new Error(explain(e)); });
    },
    resetPassword(email) { return auth.sendPasswordResetEmail(email.trim()).catch((e) => { throw new Error(explain(e)); }); },
    signOut() {
      return auth.signOut().then(() => {
        localStorage.removeItem(LS_STATE_KEY); // drop the signed-in user's local copy
        location.reload();
      });
    },

    /* After an explicit sign-in/up: adopt the account's cloud state (or seed it
       from what this browser had), then reload so the engine rehydrates. */
    adoptAccountState() {
      if (!db || !auth.currentUser) return Promise.resolve();
      return stateDoc().get().then((snap) => {
        if (snap.exists && snap.data().state) {
          localStorage.setItem(LS_STATE_KEY, snap.data().state);
        } else {
          const local = localStorage.getItem(LS_STATE_KEY);
          if (local) return stateDoc().set({ state: local, updatedAt: firebase.firestore.FieldValue.serverTimestamp() });
        }
      }).catch(() => {});
    },

    /* ---- per-user state mirror (called by the engine on every persist) ---- */
    load() {
      if (!db) return Promise.resolve(null);
      return stateDoc().get()
        .then((snap) => (snap.exists && snap.data().state ? JSON.parse(snap.data().state) : null))
        .catch(() => null);
    },
    save(payload) {
      if (!db) return;
      clearTimeout(saveTimer);
      saveTimer = setTimeout(() => {
        stateDoc().set({
          state: JSON.stringify(payload),
          updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
        }).catch(() => {});
      }, 1500);
    },

    /* ---- shared inventory (admin writes, everyone reads) ---- */
    pushSharedInventory(customLots, lotEdits, consignors, freight) {
      if (!db || !this.isAdmin()) return;
      clearTimeout(invTimer);
      const payload = { customLots, lotEdits, freight };
      invTimer = setTimeout(() => {
        invDoc().set({
          inv: JSON.stringify(payload),
          updatedBy: auth.currentUser.email,
          updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
        }).catch((e) => console.warn("shared inventory push failed", e));
        localStorage.setItem(LS_SHARED_INV, JSON.stringify(payload)); // keep own cache in step
        // consignor email allowlist — lets consignor accounts update offers (see firestore.rules)
        if (consignors) {
          db.collection("platform").doc("consignors").set({
            emails: consignors.map((c) => (c.email || "").toLowerCase()).filter(Boolean),
          }).catch(() => {});
        }
      }, 1200);
    },

    /* ---- shared operational records: orders / offers / claims ----
       Owner (buyer) creates; owner, admin, and consignor accounts update.
       Admin subscribes to everything, users to their own. */
    opsPush(type, rec) {
      if (!db || !auth.currentUser) return;
      const owner = rec._owner || auth.currentUser.uid;
      const docId = rec._doc || `${type}-${rec.id}-${owner.slice(0, 8)}`.replace(/[^\w-]/g, "_");
      const clean = { ...rec }; delete clean._doc; delete clean._owner;
      db.collection("ops").doc(docId).set({
        type, owner,
        data: JSON.stringify(clean),
        updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
      }).catch((e) => console.warn("ops push failed", type, e && e.code));
    },
    opsWatch(cb, mode) {
      if (!db || !auth.currentUser) return () => {};
      const handler = (snap) => {
        const docs = [];
        snap.forEach((d) => {
          const v = d.data();
          try { docs.push({ docId: d.id, type: v.type, owner: v.owner, rec: JSON.parse(v.data) }); } catch (e) {}
        });
        cb(docs);
      };
      const err = (e) => console.warn("ops watch failed", e && e.code);
      if (mode === "admin") return db.collection("ops").onSnapshot(handler, err);
      const own = db.collection("ops").where("owner", "==", auth.currentUser.uid).onSnapshot(handler, err);
      if (mode !== "consignor") return own;
      const offers = db.collection("ops").where("type", "==", "offer").onSnapshot(handler, err);
      return () => { own(); offers(); };
    },
    loadSharedInventory() {
      if (!db) return Promise.resolve(null);
      return invDoc().get().then((snap) => (snap.exists && snap.data().inv ? snap.data().inv : null)).catch(() => null);
    },
  };
})();

/* ---- shared live auctions (carzello-auction Worker — the bidding authority) ---- */
const AUCTION_API = "https://carzello-auction.late-feather-360f.workers.dev";
const Auction = {
  /* signed-in callers also get their own proxy maxes + real buying power */
  list() {
    const u = FB.enabled && FB.currentUser();
    const go = (headers) => fetch(AUCTION_API + "/auctions", { headers })
      .then((r) => r.json())
      .then((d) => ({ auctions: d.auctions || {}, me: d.me || null }))
      .catch(() => null);
    return u ? u.getIdToken().then((t) => go({ authorization: "Bearer " + t })).catch(() => go()) : go();
  },
  setDeposit(email, amount) { return this._authed("/deposit", { email, amount }); },
  listDeposits() { return this._authed("/deposits", {}); },
  _authed(path, body) {
    const u = FB.enabled && FB.currentUser();
    if (!u) return Promise.resolve({ ok: false, reason: "Sign in to bid." });
    return u.getIdToken()
      .then((t) => fetch(AUCTION_API + path, {
        method: "POST",
        headers: { "content-type": "application/json", authorization: "Bearer " + t },
        body: JSON.stringify(body),
      }))
      .then((r) => r.json())
      .catch(() => ({ ok: false, reason: "Network error — try again." }));
  },
  bid(lotId, amount, proxy) { return this._authed("/bid", { lotId, amount, proxy: !!proxy }); },
  buyNow(lotId) { return this._authed("/buynow", { lotId }); },
  publish(def) { return this._authed("/publish", def); },
  close(lotId) { return this._authed("/close", { lotId }); },
};

/* Boot hydrations (async; each reloads at most once per session):
   1. shared inventory changed since our cached copy → cache + reload
   2. signed-out fresh browser with an existing device cloud copy → restore */
if (FB.enabled) {
  FB.loadSharedInventory().then((inv) => {
    if (inv && inv !== localStorage.getItem(LS_SHARED_INV) && !sessionStorage.getItem("carzello.invcycle")) {
      sessionStorage.setItem("carzello.invcycle", "1");
      localStorage.setItem(LS_SHARED_INV, inv);
      location.reload();
    }
  });
  if (!localStorage.getItem(LS_STATE_KEY) && !sessionStorage.getItem("carzello.hydrated")) {
    sessionStorage.setItem("carzello.hydrated", "1");
    FB.load().then((cloud) => {
      if (cloud) {
        try { localStorage.setItem(LS_STATE_KEY, JSON.stringify(cloud)); location.reload(); } catch (e) {}
      }
    });
  }
}
