/**
 * <plugin-tree> - Routing tree navigation for plugin configuration.
 *
 * Fetches the routing tree from /_sys/plugin_config/tree and renders
 * an expandable tree. Emits "node-selected" on click.
 */

class PluginTree extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this._treeData = null;
    this.shadowRoot.innerHTML = `
      <style>
        :host { display: block; padding: 8px; font-size: 14px; }
        .tree-node { cursor: pointer; padding: 4px 8px; border-radius: 4px; }
        .tree-node:hover { background: #e8f5e9; }
        .tree-node.selected { background: #c8e6c9; font-weight: 600; }
        .router-node { font-weight: 500; color: #1565c0; }
        .entry-node { color: #333; padding-left: 8px; }
        .expander { display: inline-block; width: 16px; cursor: pointer; user-select: none; }
        .children { padding-left: 16px; }
        .children.collapsed { display: none; }
        .badge {
          display: inline-block;
          background: #e3f2fd;
          color: #1565c0;
          font-size: 11px;
          padding: 1px 6px;
          border-radius: 8px;
          margin-left: 6px;
        }
        .placeholder {
          color: #94a3b8;
          text-align: center;
          padding: 40px;
          font-size: 1rem;
        }
      </style>
      <div id="container">
        <div class="placeholder">Loading...</div>
      </div>
    `;
  }

  async refresh() {
    try {
      const res = await fetch("/_sys/plugin_config/tree");
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      this._treeData = await res.json();
      this._render();
    } catch (err) {
      console.error("Failed to load tree:", err);
      this.shadowRoot.getElementById("container").innerHTML =
        `<div class="placeholder">Failed to load routing tree</div>`;
    }
  }

  _render() {
    const container = this.shadowRoot.getElementById("container");
    if (!this._treeData || Object.keys(this._treeData).length === 0) {
      container.innerHTML = `<div class="placeholder">No routes found</div>`;
      return;
    }
    container.innerHTML = "";
    this._renderRouter(container, this._treeData, "");
  }

  _renderRouter(parent, data, path) {
    // Render child routers
    const routers = data.routers || {};
    for (const [name, rdata] of Object.entries(routers)) {
      const childPath = path ? `${path}/${name}` : name;
      const pluginCount = Object.keys(rdata.plugin_info || {}).length;

      const wrapper = document.createElement("div");

      // Router header
      const nodeEl = document.createElement("div");
      nodeEl.className = "tree-node router-node";

      const expander = document.createElement("span");
      expander.className = "expander";
      expander.textContent = "\u25B8";
      nodeEl.appendChild(expander);

      const label = document.createElement("span");
      label.textContent = ` ${name}`;
      nodeEl.appendChild(label);

      if (pluginCount > 0) {
        const badge = document.createElement("span");
        badge.className = "badge";
        badge.textContent = `${pluginCount} plugin${pluginCount > 1 ? "s" : ""}`;
        nodeEl.appendChild(badge);
      }

      wrapper.appendChild(nodeEl);

      // Children container
      const childrenEl = document.createElement("div");
      childrenEl.className = "children collapsed";

      // Render entries for this router
      const entries = rdata.entries || {};
      for (const [ename, edata] of Object.entries(entries)) {
        const entryEl = document.createElement("div");
        entryEl.className = "tree-node entry-node";
        entryEl.textContent = `\u2022 ${ename}`;
        entryEl.addEventListener("click", (ev) => {
          ev.stopPropagation();
          this._selectNode(entryEl);
          this.dispatchEvent(new CustomEvent("node-selected", {
            detail: {
              type: "entry",
              path: childPath,
              name: ename,
              pluginInfo: rdata.plugin_info || {},
            }
          }));
        });
        childrenEl.appendChild(entryEl);
      }

      // Recurse into child routers
      this._renderRouter(childrenEl, rdata, childPath);

      wrapper.appendChild(childrenEl);

      // Expand/collapse
      expander.addEventListener("click", (ev) => {
        ev.stopPropagation();
        const isCollapsed = childrenEl.classList.contains("collapsed");
        childrenEl.classList.toggle("collapsed");
        expander.textContent = isCollapsed ? "\u25BE" : "\u25B8";
      });

      // Click on router name -> select
      nodeEl.addEventListener("click", () => {
        this._selectNode(nodeEl);
        this.dispatchEvent(new CustomEvent("node-selected", {
          detail: {
            type: "router",
            path: childPath,
            name: name,
            pluginInfo: rdata.plugin_info || {},
          }
        }));
      });

      parent.appendChild(wrapper);
    }

    // Render top-level entries (for root router)
    const entries = data.entries || {};
    for (const [ename, edata] of Object.entries(entries)) {
      const entryEl = document.createElement("div");
      entryEl.className = "tree-node entry-node";
      entryEl.textContent = `\u2022 ${ename}`;
      entryEl.addEventListener("click", (ev) => {
        ev.stopPropagation();
        this._selectNode(entryEl);
        this.dispatchEvent(new CustomEvent("node-selected", {
          detail: {
            type: "entry",
            path: path,
            name: ename,
            pluginInfo: data.plugin_info || {},
          }
        }));
      });
      parent.appendChild(entryEl);
    }
  }

  _selectNode(el) {
    // Deselect previous
    const prev = this.shadowRoot.querySelector(".selected");
    if (prev) prev.classList.remove("selected");
    el.classList.add("selected");
  }
}

customElements.define("plugin-tree", PluginTree);
