// Saloniq — Firebase client
// Initializes Firebase + exposes async helpers for the rest of the app.
//
// All security is enforced server-side via firestore.rules — the helpers here
// are convenience wrappers, not security boundaries.

(function initFirebase() {
  if (firebase.apps.length === 0) {
    firebase.initializeApp(window.SALONIQ_FIREBASE_CONFIG);
  }
})();

const fbAuth = firebase.auth();
const fbDb = firebase.firestore();

// Persist sessions across browser restarts (default is LOCAL but be explicit)
fbAuth.setPersistence(firebase.auth.Auth.Persistence.LOCAL).catch(() => {});

// Enable Firestore IndexedDB offline cache — survives reloads + computer crashes.
// Writes are queued locally if offline and replayed when network returns.
try {
  fbDb.enablePersistence({ synchronizeTabs: true }).catch(err => {
    if (err.code !== 'failed-precondition' && err.code !== 'unimplemented') {
      console.warn('Firestore persistence:', err.code, err.message);
    }
  });
} catch (e) { /* called twice or unsupported — safe to ignore */ }

// ─── Helpers ───────────────────────────────────────────────────────────────
const isSuperAdminEmail = (email) =>
  !!email && (window.SALONIQ_SUPER_ADMIN_EMAILS || []).includes(email.toLowerCase());

// Subscribe to auth-state changes; resolves user + their /users/{uid} profile.
function onAuthChange(callback) {
  return fbAuth.onAuthStateChanged(async (user) => {
    if (!user) {
      callback({ user: null, profile: null, isSuperAdmin: false });
      return;
    }
    const superAdmin = isSuperAdminEmail(user.email);
    let profile = null;
    if (!superAdmin) {
      try {
        const doc = await fbDb.collection('users').doc(user.uid).get();
        profile = doc.exists ? { id: doc.id, ...doc.data() } : null;
      } catch (e) {
        console.warn('Failed to load user profile', e);
      }
    }
    callback({ user, profile, isSuperAdmin: superAdmin });
  });
}

// ─── Auth ──────────────────────────────────────────────────────────────────
async function signIn(email, password) {
  return fbAuth.signInWithEmailAndPassword(email.trim().toLowerCase(), password);
}

async function signOut() {
  return fbAuth.signOut();
}

// ─── Salon directory ───────────────────────────────────────────────────────
async function listSalons() {
  const snap = await fbDb.collection('salons').orderBy('createdAt', 'desc').get();
  return snap.docs.map(d => ({ id: d.id, ...d.data() }));
}

async function getSalonBySubdomain(subdomain) {
  const snap = await fbDb.collection('salons')
    .where('subdomain', '==', subdomain.toLowerCase())
    .limit(1).get();
  if (snap.empty) return null;
  const doc = snap.docs[0];
  return { id: doc.id, ...doc.data() };
}

async function getSalon(salonId) {
  const doc = await fbDb.collection('salons').doc(salonId).get();
  return doc.exists ? { id: doc.id, ...doc.data() } : null;
}

// ─── Super-admin operations ────────────────────────────────────────────────
// Creates: 1) Firebase Auth user (in a SECONDARY auth instance so we don't
// kick out the super-admin), 2) /users/{uid} profile, 3) /salons/{salonId} doc.
async function createSalonWithOwner({ salonName, subdomain, color, ownerEmail, ownerPassword, ownerName }) {
  const cleanSubdomain = subdomain.toLowerCase().replace(/[^a-z0-9-]/g, '');
  const cleanEmail = ownerEmail.trim().toLowerCase();
  if (!cleanSubdomain) throw new Error('Ugyldigt subdomæne');
  if (!cleanEmail.includes('@')) throw new Error('Ugyldig email');
  if (!ownerPassword || ownerPassword.length < 6) throw new Error('Adgangskode skal være mindst 6 tegn');

  // Check subdomain isn't taken
  const existing = await getSalonBySubdomain(cleanSubdomain);
  if (existing) throw new Error('Subdomænet er allerede i brug');

  // Use a secondary auth instance so super-admin doesn't get signed out
  const secondaryAppName = '__secondary_' + Date.now();
  const secondaryApp = firebase.initializeApp(window.SALONIQ_FIREBASE_CONFIG, secondaryAppName);
  let cred;
  try {
    cred = await secondaryApp.auth().createUserWithEmailAndPassword(cleanEmail, ownerPassword);
  } finally {
    await secondaryApp.delete();
  }

  const uid = cred.user.uid;
  const salonId = cleanSubdomain;
  const now = firebase.firestore.FieldValue.serverTimestamp();

  // Create /salons/{salonId} + /users/{uid} in a batch
  const batch = fbDb.batch();
  batch.set(fbDb.collection('salons').doc(salonId), {
    name: salonName,
    subdomain: cleanSubdomain,
    color: color || '#3F4A3A',
    active: true,
    createdAt: now,
    createdBy: fbAuth.currentUser?.uid || 'super-admin',
  });
  batch.set(fbDb.collection('users').doc(uid), {
    email: cleanEmail,
    salonId,
    role: 'owner',
    name: ownerName || cleanEmail,
    createdAt: now,
  });
  await batch.commit();

  return { salonId, uid };
}

async function setSalonActive(salonId, active) {
  await fbDb.collection('salons').doc(salonId).update({ active });
}

async function deleteSalon(salonId) {
  // Delete /salons/{salonId} doc — full cascade requires a Cloud Function or manual cleanup.
  // For now we mark as inactive; super-admin can hard-delete the auth user from Firebase Console.
  await fbDb.collection('salons').doc(salonId).delete();
}

async function listSalonUsers(salonId) {
  const snap = await fbDb.collection('users').where('salonId', '==', salonId).get();
  return snap.docs.map(d => ({ id: d.id, ...d.data() }));
}

async function addSalonUser({ salonId, email, password, name, role }) {
  const cleanEmail = email.trim().toLowerCase();
  if (!cleanEmail.includes('@')) throw new Error('Ugyldig email');
  if (!password || password.length < 6) throw new Error('Adgangskode skal være mindst 6 tegn');

  const secondaryAppName = '__secondary_' + Date.now();
  const secondaryApp = firebase.initializeApp(window.SALONIQ_FIREBASE_CONFIG, secondaryAppName);
  let cred;
  try {
    cred = await secondaryApp.auth().createUserWithEmailAndPassword(cleanEmail, password);
  } finally {
    await secondaryApp.delete();
  }

  await fbDb.collection('users').doc(cred.user.uid).set({
    email: cleanEmail,
    salonId,
    role: role || 'staff',
    name: name || cleanEmail,
    createdAt: firebase.firestore.FieldValue.serverTimestamp(),
  });
  return cred.user.uid;
}

async function removeSalonUser(uid) {
  // Removes Firestore profile only; the auth user must be deleted from Firebase
  // Console (or via a Cloud Function) for full cleanup.
  await fbDb.collection('users').doc(uid).delete();
}

// Map common Firebase auth-error codes to Danish user-friendly messages
function authErrorMessage(err) {
  const code = err?.code || '';
  if (code === 'auth/wrong-password' || code === 'auth/invalid-credential' || code === 'auth/user-not-found' || code === 'auth/invalid-login-credentials')
    return 'Forkert email eller adgangskode.';
  if (code === 'auth/too-many-requests')
    return 'For mange forsøg. Vent et øjeblik og prøv igen.';
  if (code === 'auth/email-already-in-use')
    return 'Denne email er allerede brugt af en anden konto.';
  if (code === 'auth/network-request-failed')
    return 'Ingen forbindelse til serveren. Tjek dit netværk og prøv igen.';
  if (code === 'auth/weak-password')
    return 'Adgangskoden er for svag. Brug mindst 6 tegn.';
  if (code === 'auth/invalid-email')
    return 'Ugyldig email-adresse.';
  return err?.message || 'Der skete en fejl. Prøv igen.';
}

window.SaloniqFirebase = {
  auth: fbAuth, db: fbDb,
  isSuperAdminEmail, onAuthChange,
  signIn, signOut,
  listSalons, getSalonBySubdomain, getSalon,
  createSalonWithOwner, setSalonActive, deleteSalon,
  listSalonUsers, addSalonUser, removeSalonUser,
  authErrorMessage,
};

// ─── Per-salon data store ─────────────────────────────────────────────────────
// Backed by Firestore — works across devices, survives crashes via IndexedDB
// offline cache. Single doc per salon at /salons/{id}/private/state.
//
// One-time migration: if Firestore has no doc yet but localStorage does (from
// the previous localStorage-only build), upload the localStorage data and clear it.
function _privateRef(salonId) {
  return fbDb.collection('salons').doc(salonId).collection('private').doc('state');
}

async function _migrateLegacyLocal(salonId) {
  try {
    const raw = localStorage.getItem('saloniq_data_' + salonId);
    if (!raw) return null;
    const data = JSON.parse(raw);
    await _privateRef(salonId).set({
      ...data,
      _migratedFromLocalStorage: true,
      updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
    });
    localStorage.removeItem('saloniq_data_' + salonId);
    return data;
  } catch {
    return null;
  }
}

window.SaloniqSalonData = {
  // Load salon's full state. Returns Promise<data | null>.
  async load(salonId) {
    if (!salonId) return null;
    try {
      const doc = await _privateRef(salonId).get();
      if (doc.exists) return doc.data();
      // First-time load — try migrating from localStorage if present
      return await _migrateLegacyLocal(salonId);
    } catch (e) {
      console.error('Failed to load salon data', e);
      return null;
    }
  },

  // Save full state. Firestore overwrites the doc; offline writes queue.
  async save(salonId, data) {
    if (!salonId) return;
    try {
      // Firestore can't store undefined; sanitize via JSON round-trip
      const clean = JSON.parse(JSON.stringify(data || {}));
      clean.updatedAt = firebase.firestore.FieldValue.serverTimestamp();
      await _privateRef(salonId).set(clean);
    } catch (e) {
      console.error('Failed to save salon data', e);
    }
  },

  // Real-time subscription — fires whenever another device updates the doc.
  // Returns unsubscribe function.
  subscribe(salonId, callback) {
    if (!salonId) return () => {};
    return _privateRef(salonId).onSnapshot(
      doc => { if (doc.exists) callback(doc.data()); },
      err => console.warn('Salon data subscription error:', err),
    );
  },
};
