/**
 * 右侧插件栏：时钟、待办、Markdown 便签
 */
import {
  ENABLE_DATA_SYNC_KEY,
  getDataSyncEnabled,
  getDataStorageArea
} from './data-sync.js';
import { PRO_FEATURES, isFeatureEntitled } from './membership.js';
import { renderSimpleMarkdown } from './markdown-utils.js';

const DEFAULT_ORDER = ['clock', 'todo', 'notes'];
const PLUGIN_IDS = {
  clock: 'clock',
  todo: 'todo',
  notes: 'notes'
};

const SYNC_DEFAULTS = {
  enablePluginBar: true,
  showPluginClock: true,
  showPluginTodo: true,
  showPluginNotes: true,
  pluginBarOrder: DEFAULT_ORDER
};

/** sync 单项上限 8KB，分片留余量；总容量约 100KB，便签最多占约 48KB */
const NOTES_CHUNK_SIZE = 6000;
const NOTES_MAX_CHUNKS = 8;
const NOTES_META_KEY = 'pluginNotesMeta';
const NOTES_CHUNK_PREFIX = 'pluginNotesChunk_';
const TODOS_SYNC_KEY = 'pluginTodoItems';
const NOTES_MODE_KEY = 'pluginNotesMode';
const TODOS_MAX_ITEMS = 200;

function t(key, fallback = '') {
  if (typeof window.getLocalizedMessage === 'function') {
    const msg = window.getLocalizedMessage(key);
    if (msg && msg !== key) return msg;
  }
  return fallback || key;
}

function storageGet(area, keys) {
  return new Promise((resolve) => {
    chrome.storage[area].get(keys, (result) => resolve(result || {}));
  });
}

function storageSet(area, data) {
  return new Promise((resolve, reject) => {
    chrome.storage[area].set(data, () => {
      if (chrome.runtime.lastError) {
        reject(new Error(chrome.runtime.lastError.message));
        return;
      }
      resolve();
    });
  });
}

function storageRemove(area, keys) {
  return new Promise((resolve) => {
    chrome.storage[area].remove(keys, () => resolve());
  });
}

function chunkNotes(content) {
  const text = String(content || '');
  const maxLen = NOTES_CHUNK_SIZE * NOTES_MAX_CHUNKS;
  const clipped = text.length > maxLen ? text.slice(0, maxLen) : text;
  const chunks = [];
  for (let i = 0; i < clipped.length; i += NOTES_CHUNK_SIZE) {
    chunks.push(clipped.slice(i, i + NOTES_CHUNK_SIZE));
  }
  return { text: clipped, chunks };
}

function joinNotesChunks(meta, chunkMap) {
  const count = Math.min(Number(meta?.chunks) || 0, NOTES_MAX_CHUNKS);
  if (count <= 0) return '';
  let out = '';
  for (let i = 0; i < count; i++) {
    const part = chunkMap[`${NOTES_CHUNK_PREFIX}${i}`];
    if (typeof part === 'string') out += part;
  }
  return out;
}

class PluginBarManager {
  constructor() {
    this.root = null;
    this.listEl = null;
    this.toggleButton = null;
    this.settings = { ...SYNC_DEFAULTS };
    this.todos = [];
    this.notesContent = '';
    this.notesMode = 'edit';
    this.notesChunkCount = 0;
    this.dataSyncEnabled = true;
    this.clockTimer = null;
    this.sortable = null;
    this.saveNotesTimer = null;
    this.collapsed = localStorage.getItem('pluginBarCollapsed') === 'true';
    this._applyingRemoteNotes = false;
  }

  async init() {
    this.root = document.getElementById('plugin-bar');
    this.listEl = document.getElementById('plugin-bar-list');
    this.toggleButton = document.getElementById('toggle-plugin-bar');
    if (!this.root || !this.listEl) return;

    await this.loadSettings();
    this.dataSyncEnabled = await getDataSyncEnabled();
    await this.loadPluginData();
    this._pluginBarEntitled = await isFeatureEntitled(PRO_FEATURES.PLUGIN_BAR);
    this.bindToggleButton();
    this.render();
    this.bindStorageListener();
    this.bindResize();
    this.bindLanguageChange();
    this.bindDataSyncToggle();
  }

  bindDataSyncToggle() {
    window.addEventListener('datasynctoggle', async (e) => {
      const enabled = e?.detail?.enabled !== false;
      this.dataSyncEnabled = enabled;
      await this.loadPluginData();
      this.render();
    });
  }

  applyAriaLabel() {
    if (!this.root) return;
    this.root.setAttribute('aria-label', t('pluginBarAriaLabel', 'Plugin bar'));
  }

  bindToggleButton() {
    if (!this.toggleButton) return;
    this.toggleButton.addEventListener('click', () => {
      this.collapsed = !this.collapsed;
      localStorage.setItem('pluginBarCollapsed', String(this.collapsed));
      this.applyVisibility();
    });
  }

  bindLanguageChange() {
    document.addEventListener('uilanguagechange', () => {
      this.render();
    });

    chrome.storage.onChanged.addListener((changes, area) => {
      if (area === 'sync' && changes.uiLanguage) {
        setTimeout(() => this.render(), 50);
      }
    });
  }

  loadSettings() {
    return new Promise((resolve) => {
      chrome.storage.sync.get(Object.keys(SYNC_DEFAULTS), (result) => {
        this.settings = {
          enablePluginBar: result.enablePluginBar !== false,
          showPluginClock: result.showPluginClock !== false,
          showPluginTodo: result.showPluginTodo !== false,
          showPluginNotes: result.showPluginNotes !== false,
          pluginBarOrder: Array.isArray(result.pluginBarOrder) && result.pluginBarOrder.length
            ? result.pluginBarOrder.filter((id) => DEFAULT_ORDER.includes(id))
            : [...DEFAULT_ORDER]
        };
        DEFAULT_ORDER.forEach((id) => {
          if (!this.settings.pluginBarOrder.includes(id)) {
            this.settings.pluginBarOrder.push(id);
          }
        });
        resolve();
      });
    });
  }

  dataArea() {
    return getDataStorageArea(this.dataSyncEnabled);
  }

  async loadPluginData() {
    const area = this.dataArea();
    const chunkKeys = Array.from({ length: NOTES_MAX_CHUNKS }, (_, i) => `${NOTES_CHUNK_PREFIX}${i}`);
    const primary = await storageGet(area, [
      TODOS_SYNC_KEY,
      NOTES_MODE_KEY,
      NOTES_META_KEY,
      'pluginNotesContent',
      ...chunkKeys
    ]);

    // 开启同步时：尝试从 local 迁移；关闭同步时：尝试从 sync 回填 local
    const fallbackArea = area === 'sync' ? 'local' : 'sync';
    const hasTodos = Array.isArray(primary[TODOS_SYNC_KEY]);
    const hasNotes = primary[NOTES_META_KEY] != null
      || typeof primary[`${NOTES_CHUNK_PREFIX}0`] === 'string'
      || (typeof primary.pluginNotesContent === 'string' && primary.pluginNotesContent.length > 0);

    if (!hasTodos || !hasNotes) {
      const fallback = await storageGet(fallbackArea, [
        TODOS_SYNC_KEY,
        'pluginTodoItems',
        NOTES_MODE_KEY,
        'pluginNotesMode',
        NOTES_META_KEY,
        'pluginNotesContent',
        ...chunkKeys
      ]);
      const migratePayload = {};

      if (!hasTodos) {
        const todos = Array.isArray(fallback[TODOS_SYNC_KEY])
          ? fallback[TODOS_SYNC_KEY]
          : (Array.isArray(fallback.pluginTodoItems) ? fallback.pluginTodoItems : null);
        if (todos && todos.length) {
          migratePayload[TODOS_SYNC_KEY] = todos.slice(0, TODOS_MAX_ITEMS);
        }
      }

      if (!hasNotes) {
        let notesText = '';
        if (fallback[NOTES_META_KEY]) {
          notesText = joinNotesChunks(fallback[NOTES_META_KEY], fallback);
        } else if (typeof fallback.pluginNotesContent === 'string') {
          notesText = fallback.pluginNotesContent;
        }
        if (notesText) {
          const { chunks } = chunkNotes(notesText);
          migratePayload[NOTES_META_KEY] = { chunks: chunks.length, updatedAt: Date.now() };
          chunks.forEach((chunk, i) => {
            migratePayload[`${NOTES_CHUNK_PREFIX}${i}`] = chunk;
          });
        }
      }

      const mode = fallback[NOTES_MODE_KEY] || fallback.pluginNotesMode;
      if ((mode === 'preview' || mode === 'edit') && primary[NOTES_MODE_KEY] == null) {
        migratePayload[NOTES_MODE_KEY] = mode;
      }

      if (Object.keys(migratePayload).length) {
        try {
          await storageSet(area, migratePayload);
          Object.assign(primary, migratePayload);
        } catch (err) {
          console.warn('[PluginBar] migrate plugin data failed:', err);
        }
      }
    }

    this.todos = Array.isArray(primary[TODOS_SYNC_KEY])
      ? primary[TODOS_SYNC_KEY].slice(0, TODOS_MAX_ITEMS)
      : [];
    this.notesMode = primary[NOTES_MODE_KEY] === 'preview' ? 'preview' : 'edit';

    if (typeof primary.pluginNotesContent === 'string' && primary.pluginNotesContent && !primary[NOTES_META_KEY]) {
      this.notesContent = primary.pluginNotesContent;
      this.notesChunkCount = 0;
      await this.persistNotes();
      await storageRemove(area, ['pluginNotesContent']);
      return;
    }

    this.notesContent = joinNotesChunks(primary[NOTES_META_KEY], primary);
    this.notesChunkCount = Number(primary[NOTES_META_KEY]?.chunks) || 0;
  }

  /** 功能可用（设置开启且有可显示插件），不含折叠状态 */
  async isFeatureAvailableAsync() {
    if (!this.settings.enablePluginBar) return false;
    if (window.innerWidth < 960) return false;
    if (!(await isFeatureEntitled(PRO_FEATURES.PLUGIN_BAR))) return false;
    return this.getVisiblePlugins().length > 0;
  }

  isFeatureAvailable() {
    if (!this.settings.enablePluginBar) return false;
    if (window.innerWidth < 960) return false;
    // Sync path: cache last entitlement check when possible
    if (this._pluginBarEntitled === false) return false;
    return this.getVisiblePlugins().length > 0;
  }

  async refreshEntitlement() {
    this._pluginBarEntitled = await isFeatureEntitled(PRO_FEATURES.PLUGIN_BAR);
    this.applyVisibility();
  }

  isVisible() {
    return this.isFeatureAvailable() && !this.collapsed;
  }

  getVisiblePlugins() {
    const visibility = {
      clock: this.settings.showPluginClock,
      todo: this.settings.showPluginTodo,
      notes: this.settings.showPluginNotes
    };
    return this.settings.pluginBarOrder.filter((id) => visibility[id]);
  }

  applyVisibility() {
    const available = this.isFeatureAvailable();
    const visible = available && !this.collapsed;

    this.root.classList.toggle('hidden', !visible);
    this.root.classList.toggle('plugin-bar-collapsed', available && this.collapsed);
    document.body.classList.toggle('plugin-bar-visible', visible);
    document.body.style.setProperty('--plugin-bar-width', visible ? '300px' : '0px');

    this.updateToggleButton(available, visible);
  }

  updateToggleButton(available, visible) {
    if (!this.toggleButton) return;

    if (!available) {
      this.toggleButton.hidden = true;
      return;
    }

    this.toggleButton.hidden = false;
    this.toggleButton.textContent = visible ? '>' : '<';
    this.toggleButton.style.right = visible
      ? 'calc(var(--side-panel-margin, 8px) + var(--plugin-panel-width, 300px) - 1.25rem)'
      : '2rem';
    this.toggleButton.setAttribute(
      'title',
      t('togglePluginBarTitle', 'Toggle plugin bar')
    );
    this.toggleButton.setAttribute(
      'aria-label',
      t('togglePluginBarTitle', 'Toggle plugin bar')
    );
    this.toggleButton.setAttribute('aria-expanded', visible ? 'true' : 'false');
  }

  render() {
    this.applyVisibility();
    this.applyAriaLabel();
    this.destroySortable();
    this.clearClockTimer();
    this.listEl.innerHTML = '';

    const plugins = this.getVisiblePlugins();
    plugins.forEach((id) => {
      const card = this.createPluginCard(id);
      if (card) this.listEl.appendChild(card);
    });

    if (plugins.includes('clock')) {
      this.startClock();
    }

    if (plugins.length > 1 && typeof Sortable !== 'undefined') {
      this.sortable = Sortable.create(this.listEl, {
        animation: 180,
        handle: '.plugin-drag-handle',
        ghostClass: 'plugin-card-ghost',
        chosenClass: 'plugin-card-chosen',
        onEnd: () => this.persistOrder()
      });
    }

    if (typeof window.updateUILanguage === 'function') {
      window.updateUILanguage();
    }
  }

  createPluginCard(id) {
    if (id === PLUGIN_IDS.clock) return this.createClockCard();
    if (id === PLUGIN_IDS.todo) return this.createTodoCard();
    if (id === PLUGIN_IDS.notes) return this.createNotesCard();
    return null;
  }

  createCardShell(id, titleKey, titleFallback) {
    const card = document.createElement('section');
    card.className = 'plugin-card';
    card.dataset.plugin = id;

    const header = document.createElement('header');
    header.className = 'plugin-card-header';

    const handle = document.createElement('button');
    handle.type = 'button';
    handle.className = 'plugin-drag-handle';
    handle.title = t('pluginDragHint', 'Drag to reorder');
    handle.setAttribute('aria-label', t('pluginDragHint', 'Drag to reorder'));
    handle.innerHTML = '<span></span><span></span><span></span>';

    const title = document.createElement('h3');
    title.className = 'plugin-card-title';
    title.setAttribute('data-i18n', titleKey);
    title.textContent = t(titleKey, titleFallback);

    header.appendChild(handle);
    header.appendChild(title);

    const body = document.createElement('div');
    body.className = 'plugin-card-body';

    card.appendChild(header);
    card.appendChild(body);
    return { card, body };
  }

  createClockCard() {
    const { card, body } = this.createCardShell('clock', 'pluginClockTitle', 'Clock');
    body.innerHTML = `
      <div class="plugin-clock">
        <div class="plugin-clock-time" id="plugin-clock-time">--:--:--</div>
        <div class="plugin-clock-date" id="plugin-clock-date"></div>
      </div>
    `;
    return card;
  }

  createTodoCard() {
    const { card, body } = this.createCardShell('todo', 'pluginTodoTitle', 'To-Do');

    const form = document.createElement('form');
    form.className = 'plugin-todo-form';
    form.innerHTML = `
      <input type="text" class="plugin-todo-input" data-i18n-placeholder="pluginTodoPlaceholder" placeholder="${t('pluginTodoPlaceholder', 'Add a task...')}" maxlength="200" autocomplete="off">
      <button type="submit" class="plugin-todo-add" aria-label="${t('pluginTodoAdd', 'Add')}"><span class="bookmark-add-icon">+</span></button>
    `;

    const list = document.createElement('ul');
    list.className = 'plugin-todo-list';
    this.renderTodoList(list);

    form.addEventListener('submit', (e) => {
      e.preventDefault();
      const input = form.querySelector('.plugin-todo-input');
      const text = (input.value || '').trim();
      if (!text) return;
      this.todos.unshift({
        id: `todo-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
        text,
        done: false
      });
      input.value = '';
      this.persistTodos();
      this.renderTodoList(list);
    });

    body.appendChild(form);
    body.appendChild(list);
    return card;
  }

  renderTodoList(listEl) {
    listEl.innerHTML = '';
    if (!this.todos.length) {
      const empty = document.createElement('li');
      empty.className = 'plugin-todo-empty';
      empty.setAttribute('data-i18n', 'pluginTodoEmpty');
      empty.textContent = t('pluginTodoEmpty', 'No tasks yet');
      listEl.appendChild(empty);
      return;
    }

    this.todos.forEach((item) => {
      const li = document.createElement('li');
      li.className = `plugin-todo-item${item.done ? ' is-done' : ''}`;
      li.dataset.id = item.id;

      const check = document.createElement('input');
      check.type = 'checkbox';
      check.checked = !!item.done;
      check.className = 'plugin-todo-check';
      check.addEventListener('change', () => {
        item.done = check.checked;
        this.persistTodos();
        li.classList.toggle('is-done', item.done);
      });

      const text = document.createElement('span');
      text.className = 'plugin-todo-text';
      text.textContent = item.text;

      const remove = document.createElement('button');
      remove.type = 'button';
      remove.className = 'plugin-todo-remove';
      remove.setAttribute('aria-label', t('delete', 'Delete'));
      remove.textContent = '×';
      remove.addEventListener('click', () => {
        this.todos = this.todos.filter((tItem) => tItem.id !== item.id);
        this.persistTodos();
        this.renderTodoList(listEl);
      });

      li.appendChild(check);
      li.appendChild(text);
      li.appendChild(remove);
      listEl.appendChild(li);
    });
  }

  createNotesCard() {
    const { card, body } = this.createCardShell('notes', 'pluginNotesTitle', 'Notes');

    const toolbar = document.createElement('div');
    toolbar.className = 'plugin-notes-toolbar';

    const editBtn = document.createElement('button');
    editBtn.type = 'button';
    editBtn.className = 'plugin-notes-mode-btn';
    editBtn.dataset.mode = 'edit';
    editBtn.setAttribute('data-i18n', 'pluginNotesEdit');
    editBtn.textContent = t('pluginNotesEdit', 'Edit');

    const previewBtn = document.createElement('button');
    previewBtn.type = 'button';
    previewBtn.className = 'plugin-notes-mode-btn';
    previewBtn.dataset.mode = 'preview';
    previewBtn.setAttribute('data-i18n', 'pluginNotesPreview');
    previewBtn.textContent = t('pluginNotesPreview', 'Preview');

    const textarea = document.createElement('textarea');
    textarea.className = 'plugin-notes-editor';
    textarea.setAttribute('data-i18n-placeholder', 'pluginNotesPlaceholder');
    textarea.placeholder = t('pluginNotesPlaceholder', 'Write markdown notes...');
    textarea.value = this.notesContent;

    const preview = document.createElement('div');
    preview.className = 'plugin-notes-preview markdown-body';
    preview.innerHTML = renderSimpleMarkdown(this.notesContent);

    const setMode = (mode) => {
      this.notesMode = mode === 'preview' ? 'preview' : 'edit';
      editBtn.classList.toggle('active', this.notesMode === 'edit');
      previewBtn.classList.toggle('active', this.notesMode === 'preview');
      textarea.classList.toggle('hidden', this.notesMode !== 'edit');
      preview.classList.toggle('hidden', this.notesMode !== 'preview');
      if (this.notesMode === 'preview') {
        preview.innerHTML = renderSimpleMarkdown(textarea.value);
      }
      chrome.storage[this.dataArea()].set({ [NOTES_MODE_KEY]: this.notesMode });
    };

    editBtn.addEventListener('click', () => setMode('edit'));
    previewBtn.addEventListener('click', () => setMode('preview'));

    textarea.addEventListener('input', () => {
      this.notesContent = textarea.value;
      clearTimeout(this.saveNotesTimer);
      this.saveNotesTimer = setTimeout(() => {
        this.persistNotes();
      }, 500);
    });

    toolbar.appendChild(editBtn);
    toolbar.appendChild(previewBtn);
    body.appendChild(toolbar);
    body.appendChild(textarea);
    body.appendChild(preview);
    setMode(this.notesMode);
    return card;
  }

  startClock() {
    const tick = () => {
      const timeEl = document.getElementById('plugin-clock-time');
      const dateEl = document.getElementById('plugin-clock-date');
      if (!timeEl || !dateEl) return;

      const now = new Date();
      timeEl.textContent = now.toLocaleTimeString(undefined, {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false
      });
      dateEl.textContent = now.toLocaleDateString(undefined, {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric'
      });
    };

    tick();
    this.clockTimer = setInterval(tick, 1000);
  }

  clearClockTimer() {
    if (this.clockTimer) {
      clearInterval(this.clockTimer);
      this.clockTimer = null;
    }
  }

  destroySortable() {
    if (this.sortable) {
      this.sortable.destroy();
      this.sortable = null;
    }
  }

  persistOrder() {
    const visibleOrder = Array.from(this.listEl.querySelectorAll('.plugin-card'))
      .map((el) => el.dataset.plugin)
      .filter(Boolean);

    const hidden = this.settings.pluginBarOrder.filter((id) => !visibleOrder.includes(id));
    this.settings.pluginBarOrder = [...visibleOrder, ...hidden];
    chrome.storage.sync.set({ pluginBarOrder: this.settings.pluginBarOrder });
  }

  persistTodos() {
    const todos = Array.isArray(this.todos) ? this.todos.slice(0, TODOS_MAX_ITEMS) : [];
    this.todos = todos;
    chrome.storage[this.dataArea()].set({ [TODOS_SYNC_KEY]: todos }, () => {
      if (chrome.runtime.lastError) {
        console.warn('[PluginBar] persistTodos failed:', chrome.runtime.lastError.message);
      }
    });
  }

  async persistNotes() {
    const { text, chunks } = chunkNotes(this.notesContent);
    if (text !== this.notesContent) {
      this.notesContent = text;
      const editor = this.listEl?.querySelector('.plugin-notes-editor');
      if (editor && document.activeElement === editor) {
        const pos = editor.selectionStart;
        editor.value = text;
        editor.setSelectionRange(pos, pos);
      }
    }

    const payload = {
      [NOTES_META_KEY]: { chunks: chunks.length, updatedAt: Date.now() }
    };
    chunks.forEach((chunk, i) => {
      payload[`${NOTES_CHUNK_PREFIX}${i}`] = chunk;
    });

    const staleKeys = [];
    for (let i = chunks.length; i < Math.max(this.notesChunkCount, NOTES_MAX_CHUNKS); i++) {
      staleKeys.push(`${NOTES_CHUNK_PREFIX}${i}`);
    }

    const area = this.dataArea();
    try {
      await storageSet(area, payload);
      this.notesChunkCount = chunks.length;
      if (staleKeys.length) {
        await storageRemove(area, staleKeys);
      }
    } catch (err) {
      console.warn('[PluginBar] persistNotes failed:', err);
    }
  }

  applyRemoteTodos(todos) {
    this.todos = Array.isArray(todos) ? todos.slice(0, TODOS_MAX_ITEMS) : [];
    const list = this.listEl?.querySelector('.plugin-todo-list');
    if (list) this.renderTodoList(list);
  }

  applyRemoteNotes(content) {
    this.notesContent = typeof content === 'string' ? content : '';
    this._applyingRemoteNotes = true;
    const editor = this.listEl?.querySelector('.plugin-notes-editor');
    const preview = this.listEl?.querySelector('.plugin-notes-preview');
    if (editor && document.activeElement !== editor) {
      editor.value = this.notesContent;
    }
    if (preview && this.notesMode === 'preview') {
      preview.innerHTML = renderSimpleMarkdown(this.notesContent);
    }
    this._applyingRemoteNotes = false;
  }

  bindStorageListener() {
    chrome.storage.onChanged.addListener((changes, area) => {
      if (changes[ENABLE_DATA_SYNC_KEY]) {
        const enabled = changes[ENABLE_DATA_SYNC_KEY].newValue !== false;
        if (enabled !== this.dataSyncEnabled) {
          this.dataSyncEnabled = enabled;
          this.loadPluginData().then(() => this.render());
        }
      }

      // 插件可见性等设置始终在 sync
      if (area === 'sync') {
        let needRender = false;
        if (changes.enablePluginBar) {
          this.settings.enablePluginBar = changes.enablePluginBar.newValue !== false;
          needRender = true;
        }
        if (changes.showPluginClock) {
          this.settings.showPluginClock = changes.showPluginClock.newValue !== false;
          needRender = true;
        }
        if (changes.showPluginTodo) {
          this.settings.showPluginTodo = changes.showPluginTodo.newValue !== false;
          needRender = true;
        }
        if (changes.showPluginNotes) {
          this.settings.showPluginNotes = changes.showPluginNotes.newValue !== false;
          needRender = true;
        }
        if (changes.pluginBarOrder && Array.isArray(changes.pluginBarOrder.newValue)) {
          this.settings.pluginBarOrder = changes.pluginBarOrder.newValue;
          needRender = true;
        }
        if (needRender) this.render();
      }

      // todo / notes 跟随当前数据存储区域
      if (area !== this.dataArea()) return;

      if (changes[TODOS_SYNC_KEY] && Array.isArray(changes[TODOS_SYNC_KEY].newValue)) {
        this.applyRemoteTodos(changes[TODOS_SYNC_KEY].newValue);
      }

      if (changes[NOTES_MODE_KEY]) {
        const mode = changes[NOTES_MODE_KEY].newValue === 'preview' ? 'preview' : 'edit';
        if (mode !== this.notesMode) {
          this.notesMode = mode;
          const editBtn = this.listEl?.querySelector('.plugin-notes-mode-btn[data-mode="edit"]');
          const previewBtn = this.listEl?.querySelector('.plugin-notes-mode-btn[data-mode="preview"]');
          const editor = this.listEl?.querySelector('.plugin-notes-editor');
          const preview = this.listEl?.querySelector('.plugin-notes-preview');
          if (editBtn && previewBtn && editor && preview) {
            editBtn.classList.toggle('active', mode === 'edit');
            previewBtn.classList.toggle('active', mode === 'preview');
            editor.classList.toggle('hidden', mode !== 'edit');
            preview.classList.toggle('hidden', mode !== 'preview');
            if (mode === 'preview') {
              preview.innerHTML = renderSimpleMarkdown(editor.value || this.notesContent);
            }
          }
        }
      }

      const notesChanged = changes[NOTES_META_KEY]
        || Object.keys(changes).some((k) => k.startsWith(NOTES_CHUNK_PREFIX))
        || changes.pluginNotesContent;
      if (notesChanged) {
        this.reloadNotesFromStorage();
      }
    });
  }

  async reloadNotesFromStorage() {
    // 本地正在编辑/保存时，避免远端回写覆盖未提交内容
    if (this._applyingRemoteNotes || this.saveNotesTimer) return;
    const editor = this.listEl?.querySelector('.plugin-notes-editor');
    if (editor && document.activeElement === editor) return;

    const chunkKeys = Array.from({ length: NOTES_MAX_CHUNKS }, (_, i) => `${NOTES_CHUNK_PREFIX}${i}`);
    const result = await storageGet(this.dataArea(), [NOTES_META_KEY, 'pluginNotesContent', ...chunkKeys]);
    let content = '';
    if (result[NOTES_META_KEY]) {
      content = joinNotesChunks(result[NOTES_META_KEY], result);
      this.notesChunkCount = Number(result[NOTES_META_KEY]?.chunks) || 0;
    } else if (typeof result.pluginNotesContent === 'string') {
      content = result.pluginNotesContent;
    }
    if (content !== this.notesContent) {
      this.applyRemoteNotes(content);
    }
  }

  bindResize() {
    let timer = null;
    window.addEventListener('resize', () => {
      clearTimeout(timer);
      timer = setTimeout(() => this.applyVisibility(), 120);
    });
  }

  /** 供设置页即时调用 */
  updateFromSettings(partial) {
    Object.assign(this.settings, partial);
    this.render();
  }
}

const pluginBarManager = new PluginBarManager();

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', () => pluginBarManager.init());
} else {
  pluginBarManager.init();
}

window.pluginBarManager = pluginBarManager;
export { pluginBarManager };
