// SYK Document API Client — wraps fetch with auth, refresh, error handling
// Available globally as window.api

// ─── Config — auto-detect environment ──────────────────────────
window.API_BASE = (() => {
  // 1. If __SYK_API_BASE__ is set (window.* injection or build replace), use it
  if (typeof __SYK_API_BASE__ !== 'undefined' && __SYK_API_BASE__) return __SYK_API_BASE__;
  // 2. localhost → assume local wrangler dev
  if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
    return 'http://localhost:8787';
  }
  // 3. Production default — point to deployed worker
  return 'https://syk-document-api.attasorn-ket.workers.dev';
})();

// ─── Storage keys ──────────────────────────────────────────────
const STORAGE = {
  accessToken: 'syk_access_token',
  refreshToken: 'syk_refresh_token',
  user: 'syk_user',
};

// ─── Custom error class ────────────────────────────────────────
class ApiError extends Error {
  constructor(status, message, data) {
    super(message);
    this.status = status;
    this.data = data;
  }
}

// ─── Refresh-token mutex (prevent parallel refresh storms) ─────
let refreshPromise = null;

async function tryRefresh() {
  if (refreshPromise) return refreshPromise; // dedupe concurrent calls

  refreshPromise = (async () => {
    const rt = localStorage.getItem(STORAGE.refreshToken);
    if (!rt) return false;
    try {
      const res = await fetch(`${window.API_BASE}/api/v1/auth/refresh`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ refreshToken: rt }),
      });
      if (!res.ok) {
        // Refresh token invalid → clear all + force login
        clearAuth();
        return false;
      }
      const data = await res.json();
      localStorage.setItem(STORAGE.accessToken, data.accessToken);
      localStorage.setItem(STORAGE.refreshToken, data.refreshToken);
      return true;
    } catch {
      return false;
    } finally {
      refreshPromise = null;
    }
  })();

  return refreshPromise;
}

function clearAuth() {
  localStorage.removeItem(STORAGE.accessToken);
  localStorage.removeItem(STORAGE.refreshToken);
  localStorage.removeItem(STORAGE.user);
}

// ─── Core request function ─────────────────────────────────────
async function request(method, path, opts = {}) {
  const headers = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
  const token = localStorage.getItem(STORAGE.accessToken);
  if (token && !opts.skipAuth) headers.Authorization = `Bearer ${token}`;

  const init = { method, headers };
  if (opts.body !== undefined) {
    init.body = opts.body instanceof FormData ? opts.body : JSON.stringify(opts.body);
    if (opts.body instanceof FormData) delete headers['Content-Type']; // browser sets multipart boundary
  }

  let res;
  try {
    res = await fetch(window.API_BASE + path, init);
  } catch (netErr) {
    throw new ApiError(0, 'Network error: ' + netErr.message);
  }

  // Auto-refresh on 401 (one retry)
  if (res.status === 401 && !opts._retried && !opts.skipAuth) {
    const refreshed = await tryRefresh();
    if (refreshed) return request(method, path, { ...opts, _retried: true });
    // Refresh failed → redirect to login
    if (window.__forceLogout) window.__forceLogout();
  }

  let data = null;
  try { data = await res.json(); } catch {}

  if (!res.ok) {
    throw new ApiError(res.status, data?.error || `HTTP ${res.status}`, data);
  }
  return data;
}

// ─── Public API object ─────────────────────────────────────────
window.api = {
  // Generic methods
  get:    (path, opts)       => request('GET',    path, opts),
  post:   (path, body, opts) => request('POST',   path, { ...opts, body }),
  put:    (path, body, opts) => request('PUT',    path, { ...opts, body }),
  delete: (path, opts)       => request('DELETE', path, opts),

  // ─── Auth helpers ────────────────────────────────────────────
  async login(email, password) {
    const data = await request('POST', '/api/v1/auth/login', {
      body: { email, password },
      skipAuth: true,
    });
    localStorage.setItem(STORAGE.accessToken, data.accessToken);
    localStorage.setItem(STORAGE.refreshToken, data.refreshToken);
    localStorage.setItem(STORAGE.user, JSON.stringify(data.user));
    return data.user;
  },

  async logout() {
    const rt = localStorage.getItem(STORAGE.refreshToken);
    if (rt) {
      try { await request('POST', '/api/v1/auth/logout', { body: { refreshToken: rt } }); } catch {}
    }
    clearAuth();
  },

  async refreshUser() {
    const data = await request('GET', '/api/v1/auth/me');
    if (data?.user) localStorage.setItem(STORAGE.user, JSON.stringify(data.user));
    return data.user;
  },

  getCurrentUser() {
    const u = localStorage.getItem(STORAGE.user);
    return u ? JSON.parse(u) : null;
  },

  isAuthenticated() {
    return !!localStorage.getItem(STORAGE.accessToken);
  },

  // ─── Resource helpers (parity with window.electron interface) ─
  // Projects
  getProjects:    ()         => request('GET', '/api/v1/projects').then(r => r.data),
  getProject:     (id)       => request('GET', `/api/v1/projects/${id}`).then(r => r.data),
  insertProject:  (data)     => request('POST', '/api/v1/projects', { body: data }),
  updateProject:  (id, data) => request('PUT', `/api/v1/projects/${id}`, { body: data }),
  deleteProject:  (id)       => request('DELETE', `/api/v1/projects/${id}`),

  // BOQ
  getBOQs:        (pid)      => request('GET', `/api/v1/boq${pid ? '?project_id=' + pid : ''}`).then(r => r.data),
  boqDraftList:   ()         => request('GET', '/api/v1/boq').then(r => r.data),
  boqDraftGet:    (id)       => request('GET', `/api/v1/boq/${id}`).then(r => r.data),
  boqDraftSave:   (draft)    => draft.id
    ? request('PUT', `/api/v1/boq/${draft.id}`, { body: draft }).then(r => ({ success: true, id: draft.id }))
    : request('POST', '/api/v1/boq', { body: draft }).then(r => ({ success: true, id: r.data?.id })),
  boqDraftDelete: (id)       => request('DELETE', `/api/v1/boq/${id}`),
  boqDraftToContract: (id)   => request('POST', `/api/v1/boq/${id}/to-contract`),

  // Contracts
  getContracts: (pid) => request('GET', '/api/v1/contracts').then(r => r.data),

  // Drawings
  getDrawings:      () => request('GET', '/api/v1/drawings').then(r => r.data),
  drawingFolderList: () => request('GET', '/api/v1/drawings/folders').then(r => r.data),
  drawingGetPdfUrl: async (id) => ({
    success: true,
    url: `${window.API_BASE}/api/v1/drawings/${id}/download?token=${localStorage.getItem(STORAGE.accessToken)}`,
  }),

  // Users
  getUsers:    () => request('GET', '/api/v1/users').then(r => r.data),
  createUser:  (data) => request('POST', '/api/v1/users', { body: data }),
  updateUser:  (id, data) => request('PUT', `/api/v1/users/${id}`, { body: data }),
  deleteUser:  (id) => request('DELETE', `/api/v1/users/${id}`),
  setUserRole: (id, role) => request('PUT', `/api/v1/users/${id}/role`, { body: { role } }),

  // Subcontractors
  getSubcontractors: () => request('GET', '/api/v1/subcontractors').then(r => r.data),

  // Audit
  auditList:    (params) => {
    const q = new URLSearchParams(params || {}).toString();
    return request('GET', '/api/v1/audit' + (q ? '?' + q : '')).then(r => r.data);
  },
  auditSummary: () => request('GET', '/api/v1/audit/summary').then(r => r),

  // Backup (web mode: not supported — server-side backup runs on schedule)
  backupDatabase: () => Promise.resolve({ success: false, error: 'Use Cloudflare D1 backups in web mode' }),
};

window.ApiError = ApiError;

// ─── Environment detection ─────────────────────────────────────
window.SYK_MODE = window.electron ? 'electron' : 'web';
console.log(`[SYK] Mode: ${window.SYK_MODE}, API: ${window.API_BASE}`);
