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

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

const API = import.meta.env.VITE_API_BASE_URL || "http://localhost:8000";

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

// Holt CSRF 
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 ? { "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 {
      /* Hi */
    }
  }

  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) {
  const qs =
    params && typeof params === "object"
      ? "?" +
        Object.entries(params)
          .filter(([, v]) => v !== undefined && v !== null)
          .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
          .join("&")
      : "";
  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 & Favorites ===================== */

// Parametrische Liste (Suche/Filter/Sort/Paging)
export function listUsers(params = {}) {
  return getJson("/users/", params); // trailing slash beibehalten
}

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" });
}

// Sicherheitsaktionen (Admin/Manager)
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),
  });
}

/* ===================== 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 getCsrfMaybe() }, // multipart: kein Content-Type setzen
  });
  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 (Manager/Admin) ===================== */

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" });
}

/* ===================== 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 });
}

/* ===================== 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 });
}

/* ===================== 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 } = {}) {
  return getJson("/transactions", { limit, offset });
}

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

// Liste aller Kategorien (Array<string>)
export function getCategories() {
  return request("/categories/"); // trailing slash wie bei /products/
}

// Kategorie umbenennen: alle Produkte mit old_name -> new_name
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" });
}

// Kategorie löschen, optional umhängen (reassign_to)
// Wenn reassignTo null/undefined ist, wird category auf NULL gesetzt
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" });
}

/* ================== Transaktionen Tracker ==============*/

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),
  });
}

// ===================== NEU: Stats (öffentlich, aber auth-pflichtig) =====================
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 });
}



let CSRF = { token: null, header: "X-CSRF-Token", fetchedAt: 0 };

async function ensureCsrf() {
  if (CSRF.token && Date.now() - CSRF.fetchedAt < 5 * 60 * 1000) return CSRF;
  const res = await fetch(API + "/auth/csrf", { credentials: "include" });
  let data = {};
  try { data = await res.json(); } catch {}
  CSRF.token =
    data?.token || data?.csrf || data?.csrf_token || data?.value || null;
  CSRF.header =
    data?.header_name || data?.header || CSRF.header; // Server kann den Headernamen mitliefern
  CSRF.fetchedAt = Date.now();
  if (!CSRF.token) throw new Error("CSRF token missing from /auth/csrf");
  return CSRF;
}

async function req(path, opts = {}) {
  const method = (opts.method || "GET").toUpperCase();
  const isMutating = method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE";

  const headers = { "Content-Type": "application/json", ...(opts.headers || {}) };

  if (isMutating) {
    const { token, header } = await ensureCsrf(); // <- WICHTIG
    headers[header] = token;
  }

  const res = await fetch(API + path, {
    credentials: "include",
    headers,
    ...opts,
  });

  if (!res.ok) {
    const text = await res.text();
    throw new Error(text || res.statusText);
  }
  return res.status === 204 ? null : res.json();
}

export async function listTopupsAdmin({ limit = 200, offset = 0, status_filter, user_id } = {}) {
  const qs = new URLSearchParams({ limit, offset });
  if (status_filter) qs.set("status_filter", status_filter);
  if (user_id) qs.set("user_id", user_id);
  return req(`/topups?${qs.toString()}`);
}



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

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


export async function getUsersLite({ limit = 200, offset = 0 } = {}) {
  const lim = Math.min(Number(limit) || 200, 200);
  return req(`/users?limit=${lim}&offset=${offset}`);
}
