/* global INITIAL_BOARDS, INITIAL_COLUMNS, INITIAL_CARDS */
/*
 * API client — single seam between the UI and "where data comes from".
 *
 * Today: returns mocks. Tomorrow: hits Supabase REST for CRUD and the Python
 * Worker for special endpoints (move, search, invite, …).
 *
 * Migration plan (see backend/ARCHITECTURE.md §13):
 *   - Replace `_mock(...)` calls with `supabase.from(...).select(...)` etc.
 *   - Keep the same return shape so callers don't have to change.
 *
 * Components should depend on `window.api`, not on `INITIAL_*` directly.
 */

const SUPABASE_URL = window.__ENV?.SUPABASE_URL || "";
const SUPABASE_ANON_KEY = window.__ENV?.SUPABASE_ANON_KEY || "";
const API_BASE = window.__ENV?.API_BASE || "";
const USE_REAL_BACKEND = Boolean(SUPABASE_URL && SUPABASE_ANON_KEY);

// Tiny helper so all mock returns look async.
const _mock = (data) => Promise.resolve(structuredClone(data));

// Local in-memory store for the mock backend, so optimistic updates persist
// during the session.
const _state = {
  boards: structuredClone(INITIAL_BOARDS),
  columns: structuredClone(INITIAL_COLUMNS),
  cards: structuredClone(INITIAL_CARDS),
};

const api = {
  // ------ session / auth (stubs) ------------------------------------------
  async getSession() {
    if (!USE_REAL_BACKEND) return _mock({ user: { id: "demo", name: "João Pereira", email: "joao@acme.com" } });
    // TODO: supabase.auth.getSession()
    throw new Error("not implemented");
  },

  async signInWithGoogle() {
    if (!USE_REAL_BACKEND) {
      console.warn("[api] signInWithGoogle: backend not configured, staying in mock mode");
      return null;
    }
    // TODO: supabase.auth.signInWithOAuth({ provider: 'google' })
    throw new Error("not implemented");
  },

  async signOut() {
    if (!USE_REAL_BACKEND) return null;
    // TODO: supabase.auth.signOut()
    throw new Error("not implemented");
  },

  // ------ boards / columns / cards ----------------------------------------
  async listBoards() {
    if (!USE_REAL_BACKEND) return _mock(_state.boards);
    // TODO: supabase.from('boards').select('*').order('position')
    throw new Error("not implemented");
  },

  async listColumns() {
    if (!USE_REAL_BACKEND) return _mock(_state.columns);
    throw new Error("not implemented");
  },

  async listCards() {
    if (!USE_REAL_BACKEND) return _mock(_state.cards);
    throw new Error("not implemented");
  },

  async createCard(columnId, title) {
    const id = "n" + Date.now();
    const newCard = {
      id, title, desc: "",
      tags: [], priority: "med", due: null,
      assignees: ["João Pereira"],
      comments: 0, attachments: 0, checklist: null, completed: false,
    };
    if (!USE_REAL_BACKEND) {
      _state.cards[id] = newCard;
      _state.columns[columnId] = {
        ..._state.columns[columnId],
        cards: [..._state.columns[columnId].cards, id],
      };
      return _mock(newCard);
    }
    // TODO: supabase.from('cards').insert(...)
    throw new Error("not implemented");
  },

  async updateCard(cardId, patch) {
    if (!USE_REAL_BACKEND) {
      _state.cards[cardId] = { ..._state.cards[cardId], ...patch };
      return _mock(_state.cards[cardId]);
    }
    // TODO: supabase.from('cards').update(patch).eq('id', cardId)
    throw new Error("not implemented");
  },

  async moveCard(cardId, toColumnId, beforeCardId = null) {
    if (!USE_REAL_BACKEND) {
      // Remove from current column
      for (const k of Object.keys(_state.columns)) {
        if (_state.columns[k].cards.includes(cardId)) {
          _state.columns[k] = {
            ..._state.columns[k],
            cards: _state.columns[k].cards.filter((id) => id !== cardId),
          };
        }
      }
      // Insert into target column at the right spot
      const targetCards = [..._state.columns[toColumnId].cards];
      if (beforeCardId) {
        const idx = targetCards.indexOf(beforeCardId);
        targetCards.splice(idx >= 0 ? idx : targetCards.length, 0, cardId);
      } else {
        targetCards.push(cardId);
      }
      _state.columns[toColumnId] = { ..._state.columns[toColumnId], cards: targetCards };
      return _mock({ ok: true });
    }
    // TODO: POST {API_BASE}/api/cards/{cardId}/move
    const res = await fetch(`${API_BASE}/api/cards/${cardId}/move`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${await _getAccessToken()}`,
      },
      body: JSON.stringify({ column_id: toColumnId, before_card_id: beforeCardId }),
    });
    if (!res.ok) throw new Error(`moveCard failed: ${res.status}`);
    return res.json();
  },

  // ------ search ----------------------------------------------------------
  async search(query, workspaceId) {
    if (!USE_REAL_BACKEND) {
      const f = query.toLowerCase();
      const hits = Object.values(_state.cards)
        .filter((c) => c.title.toLowerCase().includes(f) || (c.desc || "").toLowerCase().includes(f))
        .map((c) => ({ kind: "card", id: c.id, title: c.title, snippet: c.desc || null }));
      return _mock({ query, hits });
    }
    const res = await fetch(`${API_BASE}/api/search?q=${encodeURIComponent(query)}&workspace=${workspaceId}`, {
      headers: { "Authorization": `Bearer ${await _getAccessToken()}` },
    });
    if (!res.ok) throw new Error(`search failed: ${res.status}`);
    return res.json();
  },

  // ------ realtime (placeholders) -----------------------------------------
  subscribeToBoard(boardId, onEvent) {
    if (!USE_REAL_BACKEND) {
      // No real-time in mock mode. Return a noop unsubscriber.
      return () => {};
    }
    // TODO: supabase.channel(`board:${boardId}`).on('postgres_changes', ..., onEvent).subscribe()
    throw new Error("not implemented");
  },
};

async function _getAccessToken() {
  // TODO: read from supabase.auth.getSession()
  throw new Error("not implemented");
}

window.api = api;
window.USE_REAL_BACKEND = USE_REAL_BACKEND;
