/**
 * <folk-forum-dashboard> — Discourse instance provisioner dashboard.
 *
 * Lists user's forum instances, shows provisioning status, and allows
 * creating new instances.
 */

import { forumSchema, FORUM_DOC_ID, type ForumDoc } from "../schemas";
import type { DocumentId } from "../../../shared/local-first/document";
import { TourEngine } from "../../../shared/tour-engine";
import { ViewHistory } from "../../../shared/view-history.js";
import { startPresenceHeartbeat } from '../../../shared/collab-presence';

class FolkForumDashboard extends HTMLElement {
	private shadow: ShadowRoot;
	private instances: any[] = [];
	private selectedInstance: any = null;
	private selectedLogs: any[] = [];
	private view: "list" | "detail" | "create" = "list";
	private loading = false;
	private pollTimer: number | null = null;
	private space = "";
	private _offlineUnsub: (() => void) | null = null;
	private _subscribedDocIds: string[] = [];
	private _stopPresence: (() => void) | null = null;
	private _history = new ViewHistory<"list" | "detail" | "create">("list", "rforum");
	private _tour!: TourEngine;
	private static readonly TOUR_STEPS = [
		{ target: '.instance-card', title: "Forum Instances", message: "View your deployed Discourse forums — click one for status and logs.", advanceOnClick: false },
		{ target: '[data-action="show-create"]', title: "New Forum", message: "Deploy a new self-hosted Discourse forum in minutes.", advanceOnClick: true },
		{ target: '.price-card', title: "Choose a Plan", message: "Select a hosting tier based on your community size and needs.", advanceOnClick: false },
	];

	constructor() {
		super();
		this.shadow = this.attachShadow({ mode: "open" });
		this._tour = new TourEngine(
			this.shadow,
			FolkForumDashboard.TOUR_STEPS,
			"rforum_tour_done",
			() => this.shadow.host as HTMLElement,
		);
	}

	connectedCallback() {
		this.space = this.getAttribute("space") || "";
		if (this.space === "demo") { this.loadDemoData(); }
		else {
			this.subscribeOffline();
			this.render();
			this.loadInstances();
		}
		if (!localStorage.getItem("rforum_tour_done")) {
			setTimeout(() => this._tour.start(), 1200);
		}
		this._stopPresence = startPresenceHeartbeat(() => ({ module: 'rforum', context: this.selectedInstance?.name || 'Forum' }));
		window.addEventListener('rspace-view-restored', this._onViewRestored as EventListener);
	}

	private loadDemoData() {
		this.instances = [
			{ id: "1", name: "Commons Hub", domain: "commons.rforum.online", status: "active", region: "nbg1", size: "cx22", adminEmail: "admin@commons.example", vpsIp: "116.203.x.x", sslProvisioned: true },
			{ id: "2", name: "Design Guild", domain: "design.rforum.online", status: "provisioning", region: "fsn1", size: "cx22", adminEmail: "admin@design.example", vpsIp: "168.119.x.x", sslProvisioned: false },
			{ id: "3", name: "Archive Project", domain: "archive.rforum.online", status: "destroyed", region: "hel1", size: "cx22", adminEmail: "admin@archive.example", vpsIp: null, sslProvisioned: false },
		];
		this.loading = false;
		this.render();
	}

	disconnectedCallback() {
		this._history.destroy();
		window.removeEventListener('rspace-view-restored', this._onViewRestored as EventListener);
		this._stopPresence?.();
		if (this.pollTimer) clearInterval(this.pollTimer);
		this._offlineUnsub?.();
		this._offlineUnsub = null;
		const runtime = (window as any).__rspaceOfflineRuntime;
		if (runtime) {
			for (const id of this._subscribedDocIds) runtime.unsubscribe(id);
		}
		this._subscribedDocIds = [];
	}

	private async subscribeOffline() {
		const runtime = (window as any).__rspaceOfflineRuntime;
		if (!runtime?.isInitialized) return;

		try {
			// Forum uses a global doc (not space-scoped)
			const docId = FORUM_DOC_ID as DocumentId;
			const doc = await runtime.subscribe(docId, forumSchema);
			this._subscribedDocIds.push(docId);

			if (doc?.instances && Object.keys(doc.instances).length > 0 && this.instances.length === 0) {
				this.instances = Object.values((doc as ForumDoc).instances).map(inst => ({
					id: inst.id, name: inst.name, domain: inst.domain,
					status: inst.status, region: inst.region, size: inst.size,
					adminEmail: inst.adminEmail, vpsIp: inst.vpsIp,
					sslProvisioned: inst.sslProvisioned,
				}));
				this.render();
			}

			this._offlineUnsub = runtime.onChange(docId, (updated: ForumDoc) => {
				if (updated?.instances) {
					this.instances = Object.values(updated.instances).map(inst => ({
						id: inst.id, name: inst.name, domain: inst.domain,
						status: inst.status, region: inst.region, size: inst.size,
						adminEmail: inst.adminEmail, vpsIp: inst.vpsIp,
						sslProvisioned: inst.sslProvisioned,
					}));
					this.render();
				}
			});
		} catch { /* runtime unavailable */ }
	}

	private getApiBase(): string {
		const path = window.location.pathname;
		const match = path.match(/^(\/[^/]+)?\/rforum/);
		return match ? match[0] : "";
	}

	private getAuthHeaders(): Record<string, string> {
		const token = localStorage.getItem("encryptid_session");
		if (token) {
			try {
				const parsed = JSON.parse(token);
				return { "X-User-DID": parsed.did || "" };
			} catch {}
		}
		return {};
	}

	private async loadInstances() {
		this.loading = true;
		this.render();
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/instances`, { headers: this.getAuthHeaders() });
			if (res.ok) {
				const data = await res.json();
				this.instances = data.instances || [];
			}
		} catch (e) {
			console.error("[ForumDashboard] Error:", e);
		}
		this.loading = false;
		this.render();
	}

	private async loadInstanceDetail(id: string) {
		if (this.space === "demo") {
			this.selectedInstance = this.instances.find(i => i.id === id);
			const demoLogs: Record<string, any[]> = {
				"1": [
					{ step: "create_vps", status: "success", message: "Server created in nbg1" },
					{ step: "wait_ready", status: "success", message: "Server booted and SSH ready" },
					{ step: "configure_dns", status: "success", message: "DNS record set for commons.rforum.online" },
					{ step: "install_discourse", status: "success", message: "Discourse installed and configured" },
					{ step: "verify_live", status: "success", message: "Forum responding at https://commons.rforum.online" },
				],
				"2": [
					{ step: "create_vps", status: "success", message: "Server created in fsn1" },
					{ step: "wait_ready", status: "success", message: "Server booted and SSH ready" },
					{ step: "configure_dns", status: "running", message: "Configuring DNS for design.rforum.online..." },
					{ step: "install_discourse", status: "pending", message: "" },
					{ step: "verify_live", status: "pending", message: "" },
				],
				"3": [
					{ step: "create_vps", status: "success", message: "Server created in hel1" },
					{ step: "wait_ready", status: "success", message: "Server booted and SSH ready" },
					{ step: "configure_dns", status: "success", message: "DNS record set for archive.rforum.online" },
					{ step: "install_discourse", status: "success", message: "Discourse installed and configured" },
					{ step: "verify_live", status: "success", message: "Forum verified live before destruction" },
				],
			};
			this.selectedLogs = demoLogs[id] || [];
			this.view = "detail";
			this.render();
			return;
		}
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/instances/${id}`, { headers: this.getAuthHeaders() });
			if (res.ok) {
				const data = await res.json();
				this.selectedInstance = data.instance;
				this.selectedLogs = data.logs || [];
				this.view = "detail";
				this.render();

				// Poll if provisioning
				const active = ["pending", "provisioning", "installing", "configuring"];
				if (active.includes(this.selectedInstance.status)) {
					if (this.pollTimer) clearInterval(this.pollTimer);
					this.pollTimer = setInterval(() => this.loadInstanceDetail(id), 5000) as any;
				} else {
					if (this.pollTimer) clearInterval(this.pollTimer);
				}
			}
		} catch {}
	}

	private async handleCreate(e: Event) {
		e.preventDefault();
		if (this.space === "demo") { alert("Create is disabled in demo mode."); return; }
		const form = this.shadow.querySelector("#create-form") as HTMLFormElement;
		if (!form) return;

		const name = (form.querySelector('[name="name"]') as HTMLInputElement)?.value;
		const subdomain = (form.querySelector('[name="subdomain"]') as HTMLInputElement)?.value;
		const adminEmail = (form.querySelector('[name="admin_email"]') as HTMLInputElement)?.value;
		const region = (form.querySelector('[name="region"]') as HTMLSelectElement)?.value;
		const size = (form.querySelector('[name="size"]') as HTMLSelectElement)?.value;

		if (!name || !subdomain || !adminEmail) return;

		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/instances`, {
				method: "POST",
				headers: { "Content-Type": "application/json", ...this.getAuthHeaders() },
				body: JSON.stringify({ name, subdomain, admin_email: adminEmail, region, size }),
			});
			if (res.ok) {
				const data = await res.json();
				this.view = "detail";
				this.loadInstanceDetail(data.instance.id);
			} else {
				const err = await res.json();
				alert(err.error || "Failed to create instance");
			}
		} catch {
			alert("Network error");
		}
	}

	private async handleDestroy(id: string) {
		if (this.space === "demo") { alert("Destroy is disabled in demo mode."); return; }
		if (!confirm("Are you sure you want to destroy this forum instance? This cannot be undone.")) return;
		try {
			const base = this.getApiBase();
			await fetch(`${base}/api/instances/${id}`, {
				method: "DELETE",
				headers: this.getAuthHeaders(),
			});
			this.view = "list";
			this.loadInstances();
		} catch {}
	}

	private statusBadge(status: string): string {
		const colors: Record<string, string> = {
			pending: "#fbbf24",
			provisioning: "#4f46e5",
			installing: "#4f46e5",
			configuring: "#4f46e5",
			active: "#22c55e",
			error: "#ef4444",
			destroying: "#fbbf24",
			destroyed: "#64748b",
		};
		const color = colors[status] || "#64748b";
		const pulse = ["provisioning", "installing", "configuring"].includes(status)
			? "animation: pulse 1.5s ease-in-out infinite;"
			: "";
		return `<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:600;background:${color}22;color:${color};border:1px solid ${color}44;${pulse}">${status}</span>`;
	}

	private logStepIcon(status: string): string {
		if (status === "success") return "✅";
		if (status === "error") return "❌";
		if (status === "running") return "⏳";
		return "⏭️";
	}

	private render() {
		this.shadow.innerHTML = `
		<style>
			:host { display: block; font-family: system-ui, -apple-system, sans-serif; color: var(--rs-text-primary); -webkit-tap-highlight-color: transparent; }
			* { box-sizing: border-box; }
			button, a, input, select, textarea, [role="button"] { touch-action: manipulation; }

			@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

			.rapp-nav { display: flex; gap: 8px; margin-bottom: 16px; align-items: center; min-height: 36px; }
			.rapp-nav__back { padding: 4px 10px; border-radius: 6px; border: 1px solid var(--rs-border); background: transparent; color: var(--rs-text-secondary); cursor: pointer; font-size: 13px; }
			.rapp-nav__back:hover { color: var(--rs-text-primary); border-color: var(--rs-border-strong); }
			.rapp-nav__title { font-size: 15px; font-weight: 600; flex: 1; color: var(--rs-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
			.rapp-nav__btn { padding: 6px 14px; border-radius: 6px; border: none; background: var(--rs-primary); color: #fff; font-weight: 600; cursor: pointer; font-size: 13px; }
			.rapp-nav__btn:hover { background: var(--rs-primary-hover); }
			button {
				padding: 6px 14px; border-radius: 6px; border: 1px solid var(--rs-border);
				background: transparent; color: var(--rs-text-secondary); cursor: pointer; font-size: 13px;
			}
			button:hover { color: var(--rs-text-primary); border-color: var(--rs-border-strong); }
			button.danger { background: rgba(239,68,68,0.15); border-color: rgba(239,68,68,0.3); color: var(--rs-error); }
			button.danger:hover { background: rgba(239,68,68,0.25); }

			input, select {
				background: var(--rs-input-bg); border: 1px solid var(--rs-input-border); color: var(--rs-input-text);
				padding: 8px 12px; border-radius: 4px; font-size: 13px; width: 100%;
			}
			label { display: block; font-size: 12px; color: var(--rs-text-muted); margin-bottom: 4px; }
			.form-group { margin-bottom: 14px; }
			.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

			.instance-list { display: flex; flex-direction: column; gap: 10px; }
			.instance-card {
				background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px;
				padding: 16px; cursor: pointer; transition: border-color 0.2s;
			}
			.instance-card:hover { border-color: var(--rs-primary); }
			.instance-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
			.instance-name { font-size: 16px; font-weight: 600; }
			.instance-meta { font-size: 12px; color: var(--rs-text-muted); }

			.detail-panel { background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px; padding: 20px; }
			.detail-header { display: flex; justify-content: space-between; align-items: start; margin-bottom: 16px; }
			.detail-title { font-size: 20px; font-weight: 600; }
			.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 20px; }
			.detail-item label { font-size: 11px; color: var(--rs-text-muted); text-transform: uppercase; }
			.detail-item .value { font-size: 14px; margin-top: 2px; }

			.logs-section h3 { font-size: 14px; color: var(--rs-text-secondary); margin: 0 0 12px; }
			.log-entry { display: flex; gap: 10px; align-items: start; padding: 8px 0; border-bottom: 1px solid var(--rs-border-subtle); }
			.log-icon { font-size: 16px; flex-shrink: 0; }
			.log-step { font-size: 13px; font-weight: 500; }
			.log-msg { font-size: 12px; color: var(--rs-text-muted); margin-top: 2px; }

			.empty { text-align: center; color: var(--rs-text-muted); padding: 40px 20px; }
			.loading { text-align: center; color: var(--rs-text-muted); padding: 40px; }

			.pricing { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 20px; }
			.price-card {
				background: var(--rs-bg-surface); border: 1px solid var(--rs-border); border-radius: 8px; padding: 14px;
				text-align: center; cursor: pointer; transition: border-color 0.2s;
			}
			.price-card:hover, .price-card.selected { border-color: var(--rs-primary); }
			.price-name { font-weight: 600; font-size: 14px; margin-bottom: 4px; }
			.price-cost { font-size: 18px; color: var(--rs-primary); font-weight: 700; }
			.price-specs { font-size: 11px; color: var(--rs-text-muted); margin-top: 4px; }
			@media (max-width: 768px) {
				.pricing { grid-template-columns: 1fr; }
				.form-row { grid-template-columns: 1fr; }
				.detail-grid { grid-template-columns: 1fr; }
			}
			@media (max-width: 480px) {
				.rapp-nav { gap: 4px; }
				.rapp-nav__title { font-size: 14px; }
				.rapp-nav__btn { padding: 4px 10px; font-size: 12px; }
				.instance-card { padding: 12px; }
				.instance-name { font-size: 14px; }
				.instance-meta { font-size: 11px; }
				.detail-panel { padding: 14px; }
				.detail-title { font-size: 16px; }
				.log-step { font-size: 12px; }
			}
		</style>

		${this.view === "list" ? this.renderList() : ""}
		${this.view === "detail" ? this.renderDetail() : ""}
		${this.view === "create" ? this.renderCreate() : ""}
		`;

		this.attachEvents();
		this._tour.renderOverlay();
	}

	startTour() {
		this._tour.start();
	}

	private renderList(): string {
		return `
		<div class="rapp-nav">
			<span class="rapp-nav__title">Forum Instances</span>
			<button class="rapp-nav__btn" data-action="show-create">+ New Forum</button>
			<button class="rapp-nav__btn" id="btn-tour" style="font-size:0.78rem;padding:4px 10px;opacity:0.7">Tour</button>
		</div>

		${this.loading ? '<div class="loading">Loading...</div>' : ""}
		${!this.loading && this.instances.length === 0 ? '<div class="empty">No forum instances yet. Deploy your first Discourse forum!</div>' : ""}

		<div class="instance-list">
			${this.instances.map((inst) => `
				<div class="instance-card" data-action="detail" data-id="${inst.id}" data-collab-id="forum:${inst.id}">
					<div class="instance-header">
						<span class="instance-name">${this.esc(inst.name)}</span>
						${this.statusBadge(inst.status)}
					</div>
					<div class="instance-meta">
						${inst.domain} &middot; ${inst.region} &middot; ${inst.size}
						${inst.vpsIp ? ` &middot; ${inst.vpsIp}` : ""}
					</div>
				</div>
			`).join("")}
		</div>
		`;
	}

	private renderDetail(): string {
		const inst = this.selectedInstance;
		if (!inst) return "";

		return `
		<div class="rapp-nav">
			${this._history.canGoBack ? '<button class="rapp-nav__back" data-action="back">← Forums</button>' : ''}
			<span class="rapp-nav__title">${this.esc(inst.name)}</span>
			${inst.status !== "destroyed" ? `<button class="danger" data-action="destroy" data-id="${inst.id}">Destroy</button>` : ""}
		</div>

		<div class="detail-panel">
			<div class="detail-header">
				<div>
					<div class="detail-title">${this.esc(inst.name)}</div>
					<div style="margin-top:4px">${this.statusBadge(inst.status)}</div>
				</div>
				${inst.status === "active" ? `<a href="https://${inst.domain}" target="_blank" style="color:var(--rs-primary);font-size:13px">↗ Open Forum</a>` : ""}
			</div>

			${inst.errorMessage ? `<div style="background:#7a2a2a33;border:1px solid #7a2a2a;padding:10px;border-radius:6px;margin-bottom:16px;font-size:13px;color:var(--rs-error)">${this.esc(inst.errorMessage)}</div>` : ""}

			<div class="detail-grid">
				<div class="detail-item"><label>Domain</label><div class="value">${inst.domain}</div></div>
				<div class="detail-item"><label>IP Address</label><div class="value">${inst.vpsIp || "—"}</div></div>
				<div class="detail-item"><label>Region</label><div class="value">${inst.region}</div></div>
				<div class="detail-item"><label>Server Size</label><div class="value">${inst.size}</div></div>
				<div class="detail-item"><label>Admin Email</label><div class="value">${inst.adminEmail || "—"}</div></div>
				<div class="detail-item"><label>SSL</label><div class="value">${inst.sslProvisioned ? "✅ Active" : "⏳ Pending"}</div></div>
			</div>

			<div class="logs-section">
				<h3>Provision Log</h3>
				${this.selectedLogs.length === 0 ? '<div style="color:var(--rs-text-muted);font-size:13px">No logs yet</div>' : ""}
				${this.selectedLogs.map((log) => `
					<div class="log-entry">
						<span class="log-icon">${this.logStepIcon(log.status)}</span>
						<div>
							<div class="log-step">${this.formatStep(log.step)}</div>
							<div class="log-msg">${this.esc(log.message || "")}</div>
						</div>
					</div>
				`).join("")}
			</div>
		</div>
		`;
	}

	private renderCreate(): string {
		return `
		<div class="rapp-nav">
			${this._history.canGoBack ? '<button class="rapp-nav__back" data-action="back">← Forums</button>' : ''}
			<span class="rapp-nav__title">Deploy New Forum</span>
		</div>

		<div class="detail-panel">
			<h2 style="margin:0 0 16px;font-size:18px">Deploy New Forum</h2>

			<div class="pricing">
				<div class="price-card selected" data-size="cx22">
					<div class="price-name">Starter</div>
					<div class="price-cost">€3.79/mo</div>
					<div class="price-specs">2 vCPU &middot; 4 GB &middot; ~500 users</div>
				</div>
				<div class="price-card" data-size="cx32">
					<div class="price-name">Standard</div>
					<div class="price-cost">€6.80/mo</div>
					<div class="price-specs">4 vCPU &middot; 8 GB &middot; ~2000 users</div>
				</div>
				<div class="price-card" data-size="cx42">
					<div class="price-name">Performance</div>
					<div class="price-cost">€13.80/mo</div>
					<div class="price-specs">8 vCPU &middot; 16 GB &middot; ~10k users</div>
				</div>
			</div>

			<form id="create-form">
				<div class="form-row">
					<div class="form-group">
						<label>Forum Name</label>
						<input name="name" placeholder="My Community" required>
					</div>
					<div class="form-group">
						<label>Subdomain</label>
						<div style="display:flex;align-items:center;gap:4px">
							<input name="subdomain" placeholder="my-community" required style="flex:1">
							<span style="font-size:12px;color:var(--rs-text-muted);white-space:nowrap">.rforum.online</span>
						</div>
					</div>
				</div>

				<div class="form-row">
					<div class="form-group">
						<label>Admin Email</label>
						<input name="admin_email" type="email" placeholder="admin@example.com" required>
					</div>
					<div class="form-group">
						<label>Region</label>
						<select name="region">
							<option value="nbg1">Nuremberg (EU)</option>
							<option value="fsn1">Falkenstein (EU)</option>
							<option value="hel1">Helsinki (EU)</option>
							<option value="ash">Ashburn (US East)</option>
							<option value="hil">Hillsboro (US West)</option>
						</select>
					</div>
				</div>

				<input type="hidden" name="size" value="cx22">

				<button type="submit" style="width:100%;padding:10px;font-size:14px;margin-top:8px">
					Deploy Forum
				</button>
			</form>
		</div>
		`;
	}

	private attachEvents() {
		this.shadow.querySelector("#btn-tour")?.addEventListener("click", () => this.startTour());

		this.shadow.querySelectorAll("[data-action]").forEach((el) => {
			const action = (el as HTMLElement).dataset.action!;
			const id = (el as HTMLElement).dataset.id;
			el.addEventListener("click", () => {
				if (action === "show-create") { this._history.push(this.view); this._history.push("create"); this.view = "create"; this.render(); }
				else if (action === "back") {
					this.goBack();
				}
				else if (action === "detail" && id) { this._history.push(this.view); this._history.push("detail", { id }); this.loadInstanceDetail(id); }
				else if (action === "destroy" && id) { this.handleDestroy(id); }
			});
		});

		this.shadow.querySelectorAll(".price-card").forEach((card) => {
			card.addEventListener("click", () => {
				this.shadow.querySelectorAll(".price-card").forEach((c) => c.classList.remove("selected"));
				card.classList.add("selected");
				const sizeInput = this.shadow.querySelector('[name="size"]') as HTMLInputElement;
				if (sizeInput) sizeInput.value = (card as HTMLElement).dataset.size || "cx22";
			});
		});

		const form = this.shadow.querySelector("#create-form");
		if (form) form.addEventListener("submit", (e) => this.handleCreate(e));
	}

	private _onViewRestored = (e: CustomEvent) => {
		if (e.detail?.moduleId !== 'rforum') return;
		if (this.pollTimer) clearInterval(this.pollTimer);
		this.view = e.detail.view;
		if (e.detail.view === "list") this.loadInstances();
		else this.render();
	};

	private goBack() {
		if (this.pollTimer) clearInterval(this.pollTimer);
		const prev = this._history.back();
		if (!prev) return;
		this.view = prev.view;
		if (prev.view === "list") this.loadInstances();
		else this.render();
	}

	private formatStep(step: string): string {
		const labels: Record<string, string> = {
			create_vps: "Create Server",
			wait_ready: "Wait for Boot",
			configure_dns: "Configure DNS",
			install_discourse: "Install Discourse",
			verify_live: "Verify Live",
		};
		return labels[step] || step;
	}

	private esc(s: string): string {
		const d = document.createElement("div");
		d.textContent = s || "";
		return d.innerHTML;
	}
}

customElements.define("folk-forum-dashboard", FolkForumDashboard);
