// retoor <retoor@molodetz.nl>

import { Component } from "./Component.js";
import { Http } from "../Http.js";
import { Poller } from "../Poller.js";

const POLL_INTERVAL_MS = 3000;
const FEED_CAP = 600;
const RELOAD_DELAY_MS = 1500;
const TERMINAL_KINDS = ["done", "error"];

const KIND_ICONS = {
    stage: "🧭",
    log: "📋",
    file: "📄",
    signal: "🚩",
    ai: "🤖",
    image: "🖼️",
    progress: "⏳",
    score: "🏁",
    report: "📝",
    error: "❌",
    done: "✅",
    status: "📡",
};
const KIND_ICON_FALLBACK = "🔹";

export class AppIsslopRun extends Component {
    connectedCallback() {
        this._uid = this.attr("uid");
        this._topic = this.attr("topic");
        this._eventsUrl = this.attr("events-url", `/tools/isslop/${this._uid}/events`);
        this._lastSeq = 0;
        this._finished = false;
        this._render();
        this._status = this.querySelector("[data-isslop-status]");
        this._bar = this.querySelector("[data-isslop-bar]");
        this._feed = this.querySelector("[data-isslop-feed]");
        this._subscribed = false;
        this._subscribe();
        this._poller = new Poller(() => this._poll(), POLL_INTERVAL_MS);
    }

    disconnectedCallback() {
        if (this._poller) this._poller.stop();
        if (this._subscribed && window.app && window.app.pubsub) {
            window.app.pubsub.unsubscribe(this._topic, this._onFrame);
        }
    }

    _render() {
        this.innerHTML = `
            <div class="isslop-live-head">
                <span class="isslop-live-status" data-isslop-status role="status" aria-live="polite">Waiting for the analyzer…</span>
            </div>
            <div class="isslop-progress"><div class="isslop-progress-bar" data-isslop-bar></div></div>
            <ul class="isslop-feed" data-isslop-feed role="log" aria-live="polite"></ul>
        `;
        this._loader = document.createElement("li");
        this._loader.className = "isslop-feed-item isslop-feed-loader";
        this._loader.setAttribute("aria-hidden", "true");
        this._loader.innerHTML = '<span class="isslop-loader-cursor"></span><span class="isslop-loader-text">working</span>';
        this.querySelector("[data-isslop-feed]").appendChild(this._loader);
    }

    _subscribe() {
        const app = window.app;
        if (!this._topic || !app || !app.pubsub || typeof app.pubsub.subscribe !== "function") return;
        this._onFrame = (frame) => this._apply(frame);
        app.pubsub.subscribe(this._topic, this._onFrame);
        this._subscribed = true;
    }

    async _poll() {
        if (this._finished) return;
        let payload;
        try {
            payload = await Http.getJson(`${this._eventsUrl}?after=${this._lastSeq}`);
        } catch (error) {
            return;
        }
        (payload.events || []).forEach((event) => this._apply(event));
        if (!this._finished && payload.status === "failed" && this._lastSeq === 0) {
            this._finish(false, "Analysis failed before producing events.");
        }
    }

    _apply(event) {
        if (!event || typeof event.seq !== "number") return;
        if (event.seq > 0 && event.seq <= this._lastSeq) return;
        if (event.seq > 0) this._lastSeq = event.seq;
        if (event.kind === "stage") this._status.textContent = event.message;
        if (event.kind === "progress" && event.data && event.data.total) {
            const percent = Math.min(100, Math.round((event.data.current / event.data.total) * 100));
            this._bar.style.width = `${percent}%`;
        }
        this._append(event);
        if (TERMINAL_KINDS.includes(event.kind)) {
            this._finish(event.kind === "done", event.message);
        }
    }

    _append(event) {
        const item = document.createElement("li");
        item.className = `isslop-feed-item isslop-feed-${event.kind}`;
        const icon = document.createElement("span");
        icon.className = "isslop-feed-icon";
        icon.textContent = KIND_ICONS[event.kind] || KIND_ICON_FALLBACK;
        const text = document.createElement("span");
        text.className = "isslop-feed-text";
        text.textContent = event.message;
        item.append(icon, text);
        const thumb = event.data ? event.data.thumb : null;
        if (thumb && /^[a-f0-9]{16}\.webp$/.test(thumb)) {
            const preview = document.createElement("img");
            preview.className = "isslop-feed-thumb";
            preview.src = `/tools/isslop/${this._uid}/media/${thumb}`;
            preview.alt = "";
            preview.loading = "lazy";
            item.appendChild(preview);
        }
        this._feed.appendChild(item);
        this._feed.appendChild(this._loader);
        while (this._feed.children.length > FEED_CAP) {
            this._feed.removeChild(this._feed.firstChild);
        }
        this._feed.scrollTop = this._feed.scrollHeight;
    }

    _finish(success, message) {
        if (this._finished) return;
        this._finished = true;
        if (this._loader) this._loader.remove();
        if (this._poller) this._poller.stop();
        this._bar.style.width = "100%";
        this._bar.classList.toggle("isslop-progress-failed", !success);
        this._status.textContent = success
            ? "Analysis complete, loading the report…"
            : message || "Analysis failed.";
        if (success) {
            window.setTimeout(() => window.location.reload(), RELOAD_DELAY_MS);
        }
    }
}

customElements.define("dp-isslop-run", AppIsslopRun);
