// Read CSRF token from cookie
function getCsrfToken() {
  if (typeof document === 'undefined') return '';
  const name = 'bt_csrf_token';
  const match = document.cookie.match(new RegExp(name + '=([^;]+)'));
  return match ? match[1] : '';
}

async function _fetch(method, path, body) {
  const opts = { method, headers: { 'Content-Type': 'application/json' }, credentials: 'include' };
  // Add CSRF token header for state-changing methods
  if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {
    const csrfToken = getCsrfToken();
    if (csrfToken) {
      opts.headers['x-csrf-token'] = csrfToken;
    }
  }
  if (body !== undefined) opts.body = JSON.stringify(body);
  const res = await fetch('/api' + path, opts);
  const data = await res.json();
  if (!res.ok) {
    const err = new Error(data.message || data.error || `HTTP ${res.status}`);
    err.status = res.status;
    err.data = data;
    err.details = data.details || [];
    err.code = data.code;
    throw err;
  }
  return data;
}

const get    = (path)        => _fetch('GET',    path);
const post   = (path, body)  => _fetch('POST',   path, body);
const put    = (path, body)  => _fetch('PUT',    path, body);
const del    = (path)        => _fetch('DELETE', path);

function filenameFromDisposition(value) {
  if (!value) return null;
  const match = value.match(/filename="?([^"]+)"?/i);
  return match ? match[1] : null;
}

export const api = {
  // Auth
  me:                 ()          => get('/auth/me'),
  authMode:           ()          => get('/auth/mode'),
  login:              (data)      => post('/auth/login', data),
  logout:             ()          => post('/auth/logout'),
  restoreMultiUserMode: ()        => post('/auth/restore-multi-user-mode'),
  changePassword:     (data)      => post('/auth/change-password', data),
  acknowledgePrivacy:  ()         => post('/auth/acknowledge-privacy'),
  acknowledgeVersion:  ()         => post('/auth/acknowledge-version'),
  loginHistory:        ()         => get('/auth/login-history'),

  // Admin
  hasUsers:           ()          => get('/admin/has-users'),
  adminUsers:         ()          => get('/admin/users'),
  createUser:         (data)      => post('/admin/users', data),
  resetPassword:      (id, data)  => put(`/admin/users/${id}/password`, data),
  updateUserRole:     (id, data)  => put(`/admin/users/${id}/role`, data),
  updateUserActive:   (id, data)  => put(`/admin/users/${id}/active`, data),
  deleteUser:         (id)        => del(`/admin/users/${id}`),
  authModeConfig:     ()          => get('/admin/auth-mode'),
  setAuthMode:        (data)      => put('/admin/auth-mode', data),
  testOidcConfig:     (data)      => post('/admin/auth-mode/oidc-test', data),
  adminBackups:       ()          => get('/admin/backups'),
  createAdminBackup:  ()          => post('/admin/backups'),
  deleteAdminBackup:  (id)        => del(`/admin/backups/${encodeURIComponent(id)}`),
  restoreAdminBackup: (id)        => post(`/admin/backups/${encodeURIComponent(id)}/restore`),
  adminBackupSettings: ()         => get('/admin/backups/settings'),
  saveAdminBackupSettings: (data) => put('/admin/backups/settings', data),
  runScheduledBackupNow: ()       => post('/admin/backups/run-scheduled-now'),
  adminCleanup:        ()         => get('/admin/cleanup'),
  saveAdminCleanup:    (data)     => put('/admin/cleanup', data),
  runAdminCleanup:     ()         => post('/admin/cleanup/run'),
  seedDemoData:        ()         => post('/user/seed-demo-data'),
  clearDemoData:       ()         => post('/user/clear-demo-data'),
  seededStatus:        ()         => get('/user/seeded-status'),
  downloadAdminBackup: async (id) => {
    const res = await fetch(`/api/admin/backups/${encodeURIComponent(id)}/download`, {
      credentials: 'include',
    });
    if (!res.ok) {
      let data = {};
      try { data = await res.json(); } catch {}
      throw new Error(data.error || `HTTP ${res.status}`);
    }
    return {
      blob: await res.blob(),
      filename: filenameFromDisposition(res.headers.get('Content-Disposition')) || id,
    };
  },
  importAdminBackup: async (file) => {
    const res = await fetch('/api/admin/backups/import', {
      method: 'POST',
      credentials: 'include',
      headers: { 'Content-Type': 'application/octet-stream', 'x-csrf-token': getCsrfToken() },
      body: file,
    });
    const data = await res.json();
    if (!res.ok) {
      const err = new Error(data.message || data.error || `HTTP ${res.status}`);
      err.status = res.status;
      err.data = data;
      err.details = data.details || [];
      err.code = data.code;
      throw err;
    }
    return data;
  },

  // Notifications (admin)
  notifAdmin:         ()          => get('/notifications/admin'),
  saveNotifAdmin:     (data)      => put('/notifications/admin', data),
  testEmail:          (data)      => post('/notifications/test', data),
  notifMe:            ()          => get('/notifications/me'),
  saveNotifMe:        (data)      => put('/notifications/me', data),

  // Profile
  profile:            ()          => get('/profile'),
  updateProfile:      (data)      => _fetch('PATCH', '/profile', data),
  profileSettings:    ()          => get('/profile/settings'),
  updateProfileSettings: (data)   => _fetch('PATCH', '/profile/settings', data),
  changeProfilePassword: (data)   => post('/profile/change-password', data),
  profileExports:     ()          => get('/profile/exports'),
  profileImportHistory: ()        => get('/profile/import-history'),

  // Tracker
  tracker:            (y, m)      => get(`/tracker?year=${y}&month=${m}`),
  upcomingBills:      (days = 30) => get(`/tracker/upcoming?days=${days}`),

  // Calendar
  calendar:           (y, m)      => get(`/calendar?year=${y}&month=${m}`),

  // Summary
  summary:            (y, m)      => get(`/summary?year=${y}&month=${m}`),
  saveSummaryIncome:  (data)      => put('/summary/income', data),
  getMonthlyStartingAmounts: (y, m) => get(`/monthly-starting-amounts?year=${y}&month=${m}`),
  updateMonthlyStartingAmounts: (data) => put('/monthly-starting-amounts', data),

  // Bills
  bills:              ()          => get('/bills'),
  allBills:           ()          => get('/bills?inactive=true'),
  billAudit:          (includeInactive = false) => get(`/bills/audit${includeInactive ? '?inactive=true' : ''}`),
  bill:               (id)        => get(`/bills/${id}`),
  createBill:         (data)      => post('/bills', data),
  updateBill:         (id, data)  => put(`/bills/${id}`, data),
  updateBillBalance:  (id, bal)   => _fetch('PATCH', `/bills/${id}/balance`, { current_balance: bal }),
  billAmortization:   (id, opts = {}) => {
    const params = new URLSearchParams();
    if (opts.payment)    params.set('payment',    String(opts.payment));
    if (opts.max_months) params.set('max_months', String(opts.max_months));
    const qs = params.toString();
    return get(`/bills/${id}/amortization${qs ? `?${qs}` : ''}`);
  },
  updateBillSnowball: (id, data)  => _fetch('PATCH', `/bills/${id}/snowball`, data),
  deleteBill:         (id)        => del(`/bills/${id}`),
  restoreBill:        (id)        => post(`/bills/${id}/restore`),
  togglePaid:         (id, data)  => post(`/bills/${id}/toggle-paid`, data),
  billPayments:       (id, p, l)  => get(`/bills/${id}/payments?page=${p||1}&limit=${l||20}`),
  billMonthlyState:   (id, y, m)  => get(`/bills/${id}/monthly-state?year=${y}&month=${m}`),
  saveBillMonthlyState: (id, data) => put(`/bills/${id}/monthly-state`, data),
  billHistoryRanges:  (id)        => get(`/bills/${id}/history-ranges`),
  createBillHistoryRange: (id, data) => post(`/bills/${id}/history-ranges`, data),
  updateBillHistoryRange: (id, rangeId, data) => put(`/bills/${id}/history-ranges/${rangeId}`, data),
  deleteBillHistoryRange: (id, rangeId) => del(`/bills/${id}/history-ranges/${rangeId}`),

  // Payments
  quickPay:           (data)      => post('/payments/quick', data),
  bulkPay:            (items)     => post('/payments/bulk', items),
  createPayment:      (data)      => post('/payments', data),
  updatePayment:      (id, data)  => put(`/payments/${id}`, data),
  deletePayment:      (id)        => del(`/payments/${id}`),
  restorePayment:     (id)        => post(`/payments/${id}/restore`),

  // Snowball
  snowball:             ()        => get('/snowball'),
  snowballSettings:     ()        => get('/snowball/settings'),
  saveSnowballSettings: (data)    => _fetch('PATCH', '/snowball/settings', data),
  saveSnowballOrder:    (items)   => _fetch('PATCH', '/snowball/order', items),
  snowballProjection:   ()        => get('/snowball/projection'),

  // Categories
  categories:         ()          => get('/categories'),
  createCategory:     (data)      => post('/categories', data),
  updateCategory:     (id, data)  => put(`/categories/${id}`, data),
  deleteCategory:     (id)        => del(`/categories/${id}`),
  restoreCategory:    (id)        => post(`/categories/${id}/restore`),

  // Settings
  settings:           ()          => get('/settings'),
  saveSettings:       (data)      => put('/settings', data),

  // Analytics
  analyticsSummary:   (params = {}) => {
    const qs = new URLSearchParams();
    Object.entries(params).forEach(([key, value]) => {
      if (value !== undefined && value !== null && value !== '') qs.set(key, String(value));
    });
    const query = qs.toString();
    return get(`/analytics/summary${query ? `?${query}` : ''}`);
  },

  // Status
  status:             ()          => get('/status'),

  // Version (public)
  about:              ()          => get('/about'),
  privacy:            ()          => get('/privacy'),
  aboutAdmin:         ()          => get('/about-admin'),
  roadmap:            ()          => get('/about-admin/roadmap'),
  updateStatus:       ()          => get('/version/update-status'),
  checkForUpdates:    ()          => post('/about-admin/check-updates'),
  devLog:             ()          => get('/about-admin/dev-log'),
  version:            ()          => get('/version'),
  releaseHistory:     ()          => get('/version/history'),

  // Export (returns a URL to navigate to, not a fetch)
  exportUrl:          (year, fmt) => `/api/export?year=${year}&format=${fmt||'csv'}`,

  // Spreadsheet Import
  previewSpreadsheetImport: async (file, options = {}) => {
    const params = new URLSearchParams();
    if (options.parseAllSheets) params.set('parse_all_sheets', 'true');
    if (options.defaultYear)    params.set('year',  String(options.defaultYear));
    if (options.defaultMonth)   params.set('month', String(options.defaultMonth));
    const qs  = params.toString();
    const res = await fetch(`/api/import/spreadsheet/preview${qs ? `?${qs}` : ''}`, {
      method:      'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/octet-stream',
        'x-csrf-token': getCsrfToken(),
        ...(file.name ? { 'X-Filename': file.name } : {}),
      },
      body: file,
    });
    const data = await res.json();
    if (!res.ok) {
      const err = new Error(data.message || data.error || `HTTP ${res.status}`);
      err.status = res.status;
      err.data = data;
      err.details = data.details || [];
      err.code = data.code;
      throw err;
    }
    return data;
  },
  applySpreadsheetImport: (data)  => post('/import/spreadsheet/apply', data),
  importHistory:          ()      => get('/import/history'),

  // User SQLite import
  previewUserDbImport: async (file) => {
    const res = await fetch('/api/import/user-db/preview', {
      method:      'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/octet-stream',
        'x-csrf-token': getCsrfToken(),
        ...(file.name ? { 'X-Filename': file.name } : {}),
      },
      body: file,
    });
    const data = await res.json();
    if (!res.ok) {
      const err = new Error(data.message || data.error || `HTTP ${res.status}`);
      err.status = res.status;
      err.data = data;
      err.details = data.details || [];
      err.code = data.code;
      throw err;
    }
    return data;
  },
  applyUserDbImport: (data) => post('/import/user-db/apply', data),
};
