/**
 * <log-panel> - Log viewer with polling.
 *
 * Displays LoggingPlugin output in a terminal-style panel.
 * Polls /_sys/plugin_config/logs for new entries.
 * Can filter by entry name. Will be replaced by WebSocket in the future (see #21).
 */

const POLL_INTERVAL = 2000;

class LogPanel extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this._entryFilter = "";
    this._lastTimestamp = 0;
    this._pollTimer = null;
    this._autoScroll = true;
    this.shadowRoot.innerHTML = `
      <style>
        :host { display: flex; flex-direction: column; height: 100%; }
        .log-toolbar {
          display: flex;
          align-items: center;
          gap: 10px;
          padding: 4px 12px;
          background: #2d2d2d;
          border-bottom: 1px solid #444;
          font-size: 12px;
          color: #ccc;
        }
        .log-toolbar .title {
          font-weight: 600;
          color: #8bc34a;
        }
        .log-toolbar .filter {
          color: #64b5f6;
        }
        .log-toolbar button {
          padding: 2px 10px;
          background: #444;
          color: #ccc;
          border: 1px solid #555;
          border-radius: 3px;
          cursor: pointer;
          font-size: 11px;
        }
        .log-toolbar button:hover { background: #555; }
        .log-toolbar button.active {
          background: #2e7d32;
          border-color: #4caf50;
          color: white;
        }
        .log-toolbar .spacer { flex: 1; }
        .log-body {
          flex: 1;
          overflow-y: auto;
          padding: 6px 12px;
          font-family: "SF Mono", "Fira Code", "Consolas", monospace;
          font-size: 12px;
          line-height: 1.5;
          color: #d4d4d4;
        }
        .log-line {
          white-space: pre;
        }
        .log-line .ts {
          color: #666;
        }
        .log-line .entry {
          color: #4fc3f7;
          font-weight: 500;
        }
        .log-line .msg-start {
          color: #81c784;
        }
        .log-line .msg-end {
          color: #ffb74d;
        }
        .log-line .msg {
          color: #d4d4d4;
        }
        .empty {
          color: #666;
          font-style: italic;
          padding: 10px;
          text-align: center;
        }
      </style>
      <div class="log-toolbar">
        <span class="title">Logs</span>
        <span class="filter" id="filter-label"></span>
        <span class="spacer"></span>
        <button id="poll-btn" class="active">Polling</button>
        <button id="clear-btn">Clear</button>
      </div>
      <div class="log-body" id="log-body">
        <div class="empty">No log entries</div>
      </div>
    `;
  }

  connectedCallback() {
    this._startPolling();

    this.shadowRoot.getElementById("poll-btn").addEventListener("click", () => {
      if (this._pollTimer) {
        this._stopPolling();
      } else {
        this._startPolling();
      }
    });

    this.shadowRoot.getElementById("clear-btn").addEventListener("click", async () => {
      try {
        await fetch("/_sys/plugin_config/clear_logs");
      } catch (e) { /* ignore */ }
      this._lastTimestamp = 0;
      this.shadowRoot.getElementById("log-body").innerHTML =
        `<div class="empty">No log entries</div>`;
    });
  }

  disconnectedCallback() {
    this._stopPolling();
  }

  setEntryFilter(entry) {
    this._entryFilter = entry;
    this._lastTimestamp = 0;
    this.shadowRoot.getElementById("log-body").innerHTML =
      `<div class="empty">No log entries</div>`;
    const label = this.shadowRoot.getElementById("filter-label");
    label.textContent = entry ? `filter: ${entry}` : "";
    // Fetch immediately with new filter
    this._poll();
  }

  _startPolling() {
    if (this._pollTimer) return;
    const btn = this.shadowRoot.getElementById("poll-btn");
    btn.classList.add("active");
    this._poll();
    this._pollTimer = setInterval(() => this._poll(), POLL_INTERVAL);
  }

  _stopPolling() {
    if (this._pollTimer) {
      clearInterval(this._pollTimer);
      this._pollTimer = null;
    }
    const btn = this.shadowRoot.getElementById("poll-btn");
    btn.classList.remove("active");
  }

  async _poll() {
    try {
      const params = new URLSearchParams({ since: String(this._lastTimestamp), limit: "50" });
      if (this._entryFilter) {
        params.set("entry", this._entryFilter);
      }
      const res = await fetch(`/_sys/plugin_config/logs?${params}`);
      const data = await res.json();
      const logs = data.logs || [];
      if (logs.length > 0) {
        this._appendLogs(logs);
        this._lastTimestamp = logs[logs.length - 1].timestamp;
      }
    } catch (err) {
      console.error("Log poll failed:", err);
    }
  }

  _appendLogs(logs) {
    const body = this.shadowRoot.getElementById("log-body");
    // Remove "empty" placeholder if present
    const empty = body.querySelector(".empty");
    if (empty) empty.remove();

    for (const log of logs) {
      const line = document.createElement("div");
      line.className = "log-line";

      const ts = new Date(log.timestamp * 1000);
      const timeStr = ts.toLocaleTimeString("en-US", { hour12: false, fractionalSecondDigits: 2 });

      const msgClass = log.message.includes(" start") ? "msg-start"
        : log.message.includes(" end ") ? "msg-end" : "msg";

      line.innerHTML =
        `<span class="ts">${this._esc(timeStr)}</span> ` +
        `<span class="entry">${this._esc(log.entry_name || "-")}</span> ` +
        `<span class="${msgClass}">${this._esc(log.message)}</span>`;

      body.appendChild(line);
    }

    // Auto-scroll to bottom
    if (this._autoScroll) {
      body.scrollTop = body.scrollHeight;
    }
  }

  _esc(str) {
    const div = document.createElement("div");
    div.textContent = str;
    return div.innerHTML;
  }
}

customElements.define("log-panel", LogPanel);
