// api.js
export const API_BASE = import.meta.env.VITE_API_BASE || "http://localhost:8000";

/* ===================== Cookies & CSRF ===================== */

function getCookie(name) {
  const re = new RegExp(
    "(?:^|; )" +
      name.replace(/([.$?*|{}()[\]\\\/^])/g, "\\$1") +
      "=([^;]*)"
  );
  const m = document.cookie.match(re);
  return m ? decodeURIComponent(m[1]) : null;
}

async function getCsrfMaybe() {
  const fromCookie = getCookie("bacchus_csrf");
  if (fromCookie) return fromCookie;
  const res = await fetch(`${API_BASE}/auth/csrf`, {
    method: "GET",
    credentials: "include",
    headers: { Accept: "application/json" },
  });
  if (!res.ok) throw new Error("CSRF holen fehlgeschlagen");
  const token = getCookie("bacchus_csrf");
  if (!token) throw new Error("CSRF-Cookie fehlt");
  return token;
}

export async function getCsrfToken() {
  return getCsrfMaybe();
}

/* ===================== Request-Helper ===================== */

export async function request(path, options = {}) {
  const url = `${API_BASE}${path}`;
  const method = (options.method || "GET").toUpperCase();

  const headers = {
    Accept: "application/json",
    ...(options.body !== undefined && !(options.body instanceof FormData) ? { "Content-Type": "application/json" } : {}),
    ...(options.headers || {}),
  };
  headers["X-CSRF-Token"] = await getCsrfMaybe();

  const res = await fetch(url, {
    ...options,
    method,
    headers,
    credentials: "include",
  });

  if (res.status === 204) return null;

  const text = await res.text().catch(() => "");
  let data = null;
  if (text) {
    try { data = JSON.parse(text); } catch { /* non-JSON */ }
  }

  if (!res.ok) {
    const msg = (data && (data.detail || data.message)) || text || `Fehler ${res.status}`;
    const err = new Error(msg);
    err.status = res.status;
    err.response = res;
    throw err;
  }
  return data;
}

export async function getJson(path, params) {
  let qs = "";
  if (params && typeof params === "object") {
    const pairs = Object.entries(params)
      .filter(([, v]) => v !== undefined && v !== null && v !== "")
      .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
    if (pairs.length) qs = "?" + pairs.join("&"); // <— nur wenn wirklich Paare existieren
  }
  return request(`${path}${qs}`, { method: "GET" });
}


/* ===================== Auth / Session ===================== */

export function loginPin(pin) {
  return request("/auth/pin-login", {
    method: "POST",
    body: JSON.stringify({ pin }),
  });
}
export const loginWithPin = loginPin;

export function loginManagement(email, password) {
  return request("/auth/management-login", {
    method: "POST",
    body: JSON.stringify({ email, password }),
  });
}

export function logout() {
  return request("/auth/logout", { method: "POST" });
}

export function getCurrentUser() {
  return request("/auth/me");
}

export function getCapabilities() {
  return request("/auth/capabilities");
}

/* ===================== Dashboard ===================== */

export function getStatsSummary() {
  return request("/stats/summary");
}

/* ===================== Users ===================== */

export function listUsers(params = {}) {
  return getJson("/users/", params);
}

export function getUsers() {
  return listUsers();
}

export function getUserById(userId) {
  return request(`/users/${userId}`);
}

export function createUser(payload) {
  return request("/users", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

export function updateUser(userId, patch) {
  return request(`/users/${userId}`, {
    method: "PATCH",
    body: JSON.stringify(patch),
  });
}

export function deleteUser(userId) {
  return request(`/users/${userId}`, { method: "DELETE" });
}

export function setUserPin(userId, pin) {
  return request(`/users/${userId}/set-pin`, {
    method: "POST",
    body: JSON.stringify({ pin }),
  });
}

export function setUserPassword(userId, password) {
  return request(`/users/${userId}/set-password`, {
    method: "POST",
    body: JSON.stringify({ password }),
  });
}

export function adjustUserBalance(userId, amount_cents, reason) {
  return request(`/users/${userId}/adjust-balance`, {
    method: "POST",
    body: JSON.stringify({ amount_cents, reason }),
  });
}

export function getFavorites(userId) {
  return request(`/users/${userId}/favorites`);
}

export function updateFavorites(userId, favorites) {
  const arr = Array.isArray(favorites) ? favorites.map((n) => (Number(n) | 0)) : [];
  return request(`/users/${userId}/favorites`, {
    method: "PATCH",
    body: JSON.stringify(arr),
  });
}

export function replaceFavorites(userId, favorites) {
  const arr = Array.isArray(favorites) ? favorites.map((n) => (Number(n) | 0)) : [];
  return request(`/users/${userId}/favorites`, {
    method: "PUT",
    body: JSON.stringify(arr),
  });
}

// für logs/admintransactionen
function pickName(u) {
  const full = [u.first_name, u.last_name].filter(Boolean).join(" ").trim();
  return u.display_name || u.name || (full || null) || u.username || u.email || `User ${u.id}`;
}

// NEU: kein Versuch mehr, /users/lite aufzurufen → keine 422 mehr in der Konsole
export async function getUsersLite({ limit = 200, offset = 0 } = {}) {
  const data = await getJson("/users/", { limit, offset }); // nur dieser Endpoint
  const arr = Array.isArray(data?.items) ? data.items : Array.isArray(data) ? data : [];
  return arr.map(u => ({ id: u.id, name: pickName(u) }));
}


export async function getUsersMap(opts) {
  const list = await getUsersLite(opts);
  const map = {};
  for (const u of list) map[u.id] = u.name;
  return map;
}
/* ===================== Profile / Avatar ===================== */

export async function uploadAvatar(file) {
  const form = new FormData();
  form.append("file", file);

  const res = await fetch(`${API_BASE}/profile/avatar`, {
    method: "POST",
    body: form,
    credentials: "include",
    headers: { "X-CSRF-Token": await getCsrfToken() },
  });
  if (!res.ok) throw new Error(`Upload fehlgeschlagen (${res.status})`);
  return res.json();
}

export function updateOwnProfile(patch) {
  return request("/profile/me", {
    method: "PUT",
    body: JSON.stringify(patch),
  });
}

export function requestNewPin() {
  return request("/profile/request-new-pin", { method: "POST" });
}

/* ===================== Products ===================== */

export function getProducts() {
  return request("/products/"); // trailing slash vermeidet 307
}

export function getProduct(productId) {
  return request(`/products/${productId}`);
}

export function createProduct(payload) {
  return request("/products/", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

export function updateProduct(productId, patch) {
  return request(`/products/${productId}`, {
    method: "PUT",
    body: JSON.stringify(patch),
  });
}

export function deleteProduct(productId) {
  return request(`/products/${productId}`, { method: "DELETE" });
}

/* ===================== Bookings ===================== */

export function createBooking(userId, productId, amount, totalCents, comment = null) {
  const payload = {
    user_id: Number(userId),
    product_id: Number(productId),
    amount: Number(amount),
    total_cents: Number(totalCents),
    ...(comment ? { comment } : {}),
  };
  return request("/bookings/", { method: "POST", body: JSON.stringify(payload) });
}

export function getMyBookings({ limit = 100, offset = 0 } = {}) {
  return getJson("/bookings/me", { limit, offset });
}

export function listBookings({ user_id, limit = 10, offset = 0 } = {}) {
  return getJson("/bookings/", { user_id, limit, offset });
}

/* ===================== Deliveries ===================== */

export function getDeliveries() {
  return request("/deliveries/");
}
export function getDelivery(id) {
  return request(`/deliveries/${id}`);
}
export function createDelivery(payload) {
  return request("/deliveries/", { method: "POST", body: JSON.stringify(payload) });
}
export function deleteDelivery(id) {
  return request(`/deliveries/${id}`, { method: "DELETE" });
}

// --- utils (numeric) ---
function toInt(x) {
  return x == null || x === "" ? 0 : parseInt(x, 10) || 0;
}

export async function createDeliveryBulk(payload, products = []) {
  // payload: { supplier, date, invoice_no, note, deposit_return_cents, items:[{product_id, quantity_units, unit_cost_cents}] }

  const withUnits = {
    ...payload,                            // ← richtig, nicht ".payload"
    items: (payload.items || []).map(it => {
      const ps = (products.find(p => p.id === it.product_id)?.pack_size) ?? 1;
      return {
        ...it,                             // ← richtig, nicht ".it"
        quantity_units: toInt(it.quantity_units),
        unit_cost_cents: toInt(it.unit_cost_cents),
        units: toInt(it.quantity_units) * ps,
      };
    }),
  };

  // 1) Versuche echten Bulk-Endpoint
  try {
    return await request("/deliveries/bulk", {
      method: "POST",
      body: JSON.stringify(withUnits),
    });
  } catch (e) {
    if ([404, 405, 501].includes(e?.status)) {
      throw new Error("Server unterstützt /deliveries/bulk nicht – bitte Backend aktualisieren.");
    }
    throw e;
  }
}


// PDF-Import → Draft
export async function importDeliveryInvoice(file) {
  const form = new FormData();
  form.append("file", file);
  const res = await fetch(`${API_BASE}/deliveries/invoice/import`, {
    method: "POST",
    body: form,
    credentials: "include",
    headers: { "X-CSRF-Token": await getCsrfToken() }, // multipart: KEIN Content-Type setzen
  });
  if (!res.ok) throw new Error(await res.text());
  return res.json();
}

/* ===================== Topups (Manager/Admin) ===================== */

export function patchTopupStatus(topupId, status) {
  return request(`/topups/${topupId}/status`, {
    method: "PATCH",
    body: JSON.stringify({ status }),
  });
}

export function getMyTopups({ limit = 100, offset = 0 } = {}) {
  return getJson("/topups/me", { limit, offset });
}

export async function listTopupsAdmin({ limit = 200, offset = 0, status_filter, user_id } = {}) {
  const params = { limit, offset };
  if (status_filter) params.status_filter = status_filter;
  if (user_id) params.user_id = user_id;
  return getJson("/topups", params);
}

export async function createTopupAdmin({ user_id, amount_cents, note = "" }) {
  return request("/topups", {
    method: "POST",
    body: JSON.stringify({ user_id, amount_cents, note }),
  });
}

export async function updateTopupStatus(id, status) {
  return request(`/topups/${id}/status`, {
    method: "PATCH",
    body: JSON.stringify({ status }),
  });
}

/* ===================== Stats ===================== */

export function getConsumptionPerUser() {
  return request("/stats/consumption-per-user");
}

export function getConsumptionPerProduct() {
  return request("/stats/consumption-per-product");
}

export function getMonthlyRanking({ year, month, limit = 10 } = {}) {
  return getJson("/stats/monthly-ranking", { year, month, limit });
}

export const getStatsMeta = () => request("/stats/meta");

export function getTopDrinkers({ period = "last_delivery", category = "all", limit = 5, tz = "Europe/Berlin" } = {}) {
  return getJson("/stats/top-drinkers", { period, category, limit, tz });
}

export function getProductShare({ period = "last_delivery", tz = "Europe/Berlin" } = {}) {
  return getJson("/stats/product-share", { period, tz });
}

/* ===================== Audit / Transactions ===================== */

// Audit-Logs (Admin)
export function getAuditLogs({ limit = 100, offset = 0, user_id, action, q, date_from, date_to } = {}) {
  return getJson("/audit-logs/", { limit, offset, user_id, action, q, date_from, date_to });
}

// Eigene Transaktionen
export function getMyTransactions({ limit = 100, offset = 0 } = {}) {
  return getJson("/transactions/me", { limit, offset });
}

// Admin: alle Transaktionen
export function getTransactionsAdmin({ limit = 100, offset = 0, user_id, type, date_from, date_to } = {}) {
  return getJson("/transactions", { limit, offset, user_id, type, date_from, date_to });
}

/* ===================== Categories (Manager/Admin) ===================== */

export function getCategories() {
  return request("/categories/");
}

export function renameCategory(oldName, newName) {
  if (!oldName || !newName) throw new Error("oldName und newName sind erforderlich");
  const qs = `?old_name=${encodeURIComponent(oldName)}&new_name=${encodeURIComponent(newName)}`;
  return request(`/categories/rename${qs}`, { method: "PUT" });
}

export function deleteCategory(name, reassignTo = null) {
  if (!name) throw new Error("name ist erforderlich");
  const params = new URLSearchParams({ name });
  if (reassignTo) params.set("reassign_to", reassignTo);
  return request(`/categories/?${params.toString()}`, { method: "DELETE" });
}

/* ===================== Ledger / Topups (Self) ===================== */

export function getLedgerMe({ limit = 100, offset = 0, types = "topup,booking" } = {}) {
  return getJson("/ledger/me", { limit, offset, types });
}

export function createTopup(amount_cents, note = null) {
  const body = { amount_cents: Number(amount_cents) };
  if (note) body.note = note;
  return request("/topups/", {
    method: "POST",
    body: JSON.stringify(body),
  });
}

export function addLedgerEntry(amount_cents, note = "") {
  return request("/ledger", {
    method: "POST",
    body: JSON.stringify({ amount_cents, note }),
  });
}

/* ===================== Admin Settings (PayPal) ===================== */
export function getPaypalSettings() {
  return request("/admin/settings/paypal");
}

export function updatePaypalSettings({ paypal_me = "", paypal_receiver = "" } = {}) {
  return request("/admin/settings/paypal", {
    method: "PUT",
    body: JSON.stringify({ paypal_me, paypal_receiver }),
  });
}
