/* Crawlie blog client — shared by blog/index.html, blog/post.html, blog/admin.html.
 * If a backend API URL is configured (see backend/cloudflare-worker-blog/), all reads
 * and writes go to that real, shared backend. Otherwise everything falls back to a
 * local-only "demo mode" stored in this browser's localStorage, so the admin panel is
 * still fully usable without deployment — just not visible to other visitors. */
(function (global) {
  var API_KEY = 'crawlie_blog_api_url';
  var TOKEN_KEY = 'crawlie_blog_admin_token';
  var LOCAL_POSTS_KEY = 'crawlie_blog_local_posts';
  var SEED_VERSION_KEY = 'crawlie_blog_seed_version';
  var CURRENT_SEED_VERSION = global.CRAWLIE_BLOG_SEED_VERSION || 0;

  function getApiUrl() { try { return (localStorage.getItem(API_KEY) || '').trim(); } catch (e) { return ''; } }
  function setApiUrl(v) { try { if (v) localStorage.setItem(API_KEY, v); else localStorage.removeItem(API_KEY); } catch (e) {} }
  function getToken() { try { return (localStorage.getItem(TOKEN_KEY) || '').trim(); } catch (e) { return ''; } }
  function setToken(v) { try { if (v) localStorage.setItem(TOKEN_KEY, v); else localStorage.removeItem(TOKEN_KEY); } catch (e) {} }
  function isConfigured() { return !!getApiUrl(); }

  function seedLocalPosts() {
    var welcome = {
      slug: 'welcome-to-the-blog', title: 'Welcome to the Crawlie Blog',
      excerpt: 'This is a sample post to show how the blog looks. Edit or delete it from the admin panel.',
      content: 'This is a sample post created automatically so you can see how the blog looks before you write anything of your own.\n\nOpen the admin panel to edit this post, delete it, or add new ones. If you deploy the optional blog backend (see the backend folder in your download), posts you publish here become visible to every visitor of your site instead of just your own browser.',
      published: true, date: new Date().toISOString().slice(0, 10)
    };
    var seeded = (global.CRAWLIE_BLOG_SEED_ARTICLES && global.CRAWLIE_BLOG_SEED_ARTICLES.length) ? global.CRAWLIE_BLOG_SEED_ARTICLES : [];
    return seeded.length ? seeded.concat([welcome]) : [welcome];
  }
  function getLocalPosts() {
    try {
      var raw = localStorage.getItem(LOCAL_POSTS_KEY);
      if (!raw) {
        // First-ever visit to the blog in this browser: seed everything.
        var seeded = seedLocalPosts();
        localStorage.setItem(LOCAL_POSTS_KEY, JSON.stringify(seeded));
        localStorage.setItem(SEED_VERSION_KEY, String(CURRENT_SEED_VERSION));
        return seeded;
      }
      var posts = JSON.parse(raw);
      var storedVersion = parseInt(localStorage.getItem(SEED_VERSION_KEY) || '0', 10);
      if (storedVersion < CURRENT_SEED_VERSION) {
        // The seed article set has grown since this browser last visited (e.g. new
        // articles were added to the site after this visitor's first-ever visit).
        // Merge in anything new by slug — never touch posts already present,
        // including the welcome post or anything the visitor edited/created.
        var existingSlugs = {};
        posts.forEach(function (p) { existingSlugs[p.slug] = true; });
        (global.CRAWLIE_BLOG_SEED_ARTICLES || []).forEach(function (article) {
          if (!existingSlugs[article.slug]) posts.push(article);
        });
        saveLocalPosts(posts);
        localStorage.setItem(SEED_VERSION_KEY, String(CURRENT_SEED_VERSION));
      }
      return posts;
    } catch (e) { return []; }
  }
  function saveLocalPosts(posts) { try { localStorage.setItem(LOCAL_POSTS_KEY, JSON.stringify(posts)); } catch (e) {} }

  async function apiCall(path, options) {
    options = options || {};
    var headers = Object.assign({ 'Content-Type': 'application/json' }, options.headers || {});
    var token = getToken();
    if (token) headers['Authorization'] = 'Bearer ' + token;
    var res = await fetch(getApiUrl().replace(/\/$/, '') + path, {
      method: options.method || 'GET',
      headers: headers,
      body: options.body ? JSON.stringify(options.body) : undefined
    });
    var data = null;
    try { data = await res.json(); } catch (e) {}
    if (!res.ok) throw new Error((data && data.error) || ('HTTP ' + res.status));
    return data;
  }

  async function listPosts(includeUnpublished) {
    if (isConfigured()) {
      var data = await apiCall('/posts' + (includeUnpublished ? '?all=1' : ''));
      return data.posts || [];
    }
    var posts = getLocalPosts();
    return includeUnpublished ? posts : posts.filter(function (p) { return p.published; });
  }

  async function getPost(slug) {
    if (isConfigured()) {
      var data = await apiCall('/posts/' + encodeURIComponent(slug));
      return data.post;
    }
    var posts = getLocalPosts();
    var found = posts.filter(function (p) { return p.slug === slug; })[0];
    if (!found) throw new Error('Not found');
    return found;
  }

  async function createPost(post) {
    if (isConfigured()) {
      var data = await apiCall('/posts', { method: 'POST', body: post });
      return data.post;
    }
    var posts = getLocalPosts();
    if (posts.some(function (p) { return p.slug === post.slug; })) throw new Error('A post with this slug already exists');
    posts.push(post);
    saveLocalPosts(posts);
    return post;
  }

  async function updatePost(slug, patch) {
    if (isConfigured()) {
      var data = await apiCall('/posts/' + encodeURIComponent(slug), { method: 'PUT', body: patch });
      return data.post;
    }
    var posts = getLocalPosts();
    var idx = posts.findIndex(function (p) { return p.slug === slug; });
    if (idx === -1) throw new Error('Not found');
    posts[idx] = Object.assign({}, posts[idx], patch);
    saveLocalPosts(posts);
    return posts[idx];
  }

  async function deletePost(slug) {
    if (isConfigured()) {
      await apiCall('/posts/' + encodeURIComponent(slug), { method: 'DELETE' });
      return true;
    }
    var posts = getLocalPosts().filter(function (p) { return p.slug !== slug; });
    saveLocalPosts(posts);
    return true;
  }

  async function login(baseUrl, username, password) {
    var base = (baseUrl || '').replace(/\/$/, '');
    var res = await fetch(base + '/login.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username: username, password: password })
    });
    var data = null;
    try { data = await res.json(); } catch (e) {}
    if (!res.ok) throw new Error((data && data.error) || ('HTTP ' + res.status));
    setApiUrl(base + '/index.php');
    setToken(data.token);
    return data.token;
  }

  async function logout() {
    var api = getApiUrl();
    if (!api) { setToken(''); return; }
    var base = api.replace(/\/index\.php$/, '');
    try {
      await fetch(base + '/logout.php', { method: 'POST', headers: { 'Authorization': 'Bearer ' + getToken() } });
    } catch (e) {}
    setToken('');
  }

  global.CrawlieBlog = {
    getApiUrl: getApiUrl, setApiUrl: setApiUrl, getToken: getToken, setToken: setToken, isConfigured: isConfigured,
    listPosts: listPosts, getPost: getPost, createPost: createPost, updatePost: updatePost, deletePost: deletePost,
    login: login, logout: logout
  };
})(window);

