/**
 * <folk-choices-dashboard> — lists choice shapes (polls, rankings, spider charts)
 * from the current space and links to the canvas to create/interact with them.
 */

class FolkChoicesDashboard extends HTMLElement {
	private shadow: ShadowRoot;
	private choices: any[] = [];
	private loading = true;
	private space: string;

	/* Demo state */
	private demoTab: "spider" | "ranking" | "voting" = "spider";
	private hoveredPerson: string | null = null;
	private rankItems: { id: number; name: string; emoji: string }[] = [];
	private rankDragging: number | null = null;
	private voteOptions: { id: string; name: string; color: string; votes: number }[] = [];
	private voted = false;
	private votedId: string | null = null;
	private simTimer: number | null = null;

	constructor() {
		super();
		this.shadow = this.attachShadow({ mode: "open" });
		this.space = this.getAttribute("space") || "demo";
	}

	connectedCallback() {
		if (this.space === "demo") {
			this.loadDemoData();
			return;
		}
		this.render();
		this.loadChoices();
	}

	disconnectedCallback() {
		if (this.simTimer !== null) {
			clearInterval(this.simTimer);
			this.simTimer = null;
		}
	}

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

	private async loadChoices() {
		this.loading = true;
		this.render();
		try {
			const res = await fetch(`${this.getApiBase()}/api/choices`);
			const data = await res.json();
			this.choices = data.choices || [];
		} catch (e) {
			console.error("Failed to load choices:", e);
		}
		this.loading = false;
		this.render();
	}

	private render() {
		const typeIcons: Record<string, string> = {
			"folk-choice-vote": "☑",
			"folk-choice-rank": "📊",
			"folk-choice-spider": "🕸",
		};
		const typeLabels: Record<string, string> = {
			"folk-choice-vote": "Poll",
			"folk-choice-rank": "Ranking",
			"folk-choice-spider": "Spider Chart",
		};

		this.shadow.innerHTML = `
		<style>
			:host { display: block; padding: 1.5rem; }
			.rapp-nav { display: flex; gap: 8px; align-items: center; margin-bottom: 1rem; min-height: 36px; }
			.rapp-nav__title { font-size: 15px; font-weight: 600; flex: 1; color: #e2e8f0; }
			.create-btns { display: flex; gap: 0.5rem; }
			.create-btn { padding: 0.5rem 1rem; border-radius: 8px; border: 1px solid #334155; background: #1e293b; color: #94a3b8; cursor: pointer; font-size: 0.875rem; text-decoration: none; }
			.create-btn:hover { border-color: #6366f1; color: #f1f5f9; }
			.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; }
			.card { background: #1e293b; border: 1px solid #334155; border-radius: 12px; padding: 1.25rem; cursor: pointer; text-decoration: none; display: block; }
			.card:hover { border-color: #6366f1; }
			.card-icon { font-size: 1.5rem; margin-bottom: 0.5rem; }
			.card-title { color: #f1f5f9; font-weight: 600; font-size: 1rem; margin: 0 0 0.25rem; }
			.card-type { color: #818cf8; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
			.card-meta { color: #94a3b8; font-size: 0.8125rem; }
			.stat { display: inline-block; margin-right: 1rem; }
			.empty { text-align: center; padding: 3rem; color: #64748b; }
			.empty-icon { font-size: 3rem; margin-bottom: 1rem; }
			.empty p { margin: 0.5rem 0; font-size: 0.875rem; }
			.loading { text-align: center; padding: 3rem; color: #94a3b8; }
			.info { background: rgba(99,102,241,0.1); border: 1px solid rgba(99,102,241,0.2); border-radius: 8px; padding: 1rem; margin-bottom: 1.5rem; color: #a5b4fc; font-size: 0.8125rem; }
		</style>

		<div class="rapp-nav">
			<span class="rapp-nav__title">Choices</span>
			<div class="create-btns">
				<a class="create-btn" href="/${this.space}/rspace" title="Open canvas to create choices">➕ New on Canvas</a>
			</div>
		</div>

		<div class="info">
			Choice tools (Polls, Rankings, Spider Charts) live on the collaborative canvas.
			Create them there and they'll appear here for quick access.
		</div>

		${this.loading ? `<div class="loading">⏳ Loading choices...</div>` :
			this.choices.length === 0 ? this.renderEmpty() : this.renderGrid(typeIcons, typeLabels)}
		`;
	}

	private renderEmpty(): string {
		return `<div class="empty">
			<div class="empty-icon">☑</div>
			<p>No choices in this space yet.</p>
			<p>Open the <a href="/${this.space}/rspace" style="color:#818cf8">canvas</a> and use the Poll, Rank, or Spider buttons to create one.</p>
		</div>`;
	}

	private renderGrid(icons: Record<string, string>, labels: Record<string, string>): string {
		return `<div class="grid">
			${this.choices.map((ch) => `
			<a class="card" href="/${this.space}/rspace">
				<div class="card-icon">${icons[ch.type] || "☑"}</div>
				<div class="card-type">${labels[ch.type] || ch.type}</div>
				<h3 class="card-title">${this.esc(ch.title)}</h3>
				<div class="card-meta">
					<span class="stat">${ch.optionCount} options</span>
					<span class="stat">${ch.voteCount} responses</span>
				</div>
			</a>
			`).join("")}
		</div>`;
	}

	/* ===== Demo mode ===== */

	private loadDemoData() {
		this.rankItems = [
			{ id: 1, name: "Thai Place", emoji: "🍜" },
			{ id: 2, name: "Pizza", emoji: "🍕" },
			{ id: 3, name: "Sushi Bar", emoji: "🍣" },
			{ id: 4, name: "Tacos", emoji: "🌮" },
			{ id: 5, name: "Burgers", emoji: "🍔" },
		];
		this.voteOptions = [
			{ id: "action", name: "Action Movie", color: "#ef4444", votes: 2 },
			{ id: "comedy", name: "Comedy", color: "#f59e0b", votes: 3 },
			{ id: "horror", name: "Horror", color: "#8b5cf6", votes: 1 },
			{ id: "scifi", name: "Sci-Fi", color: "#06b6d4", votes: 2 },
		];
		this.voted = false;
		this.votedId = null;
		this.startVoteSim();
		this.renderDemo();
	}

	private startVoteSim() {
		if (this.simTimer !== null) clearInterval(this.simTimer);
		const tick = () => {
			if (this.voted) return;
			const idx = Math.floor(Math.random() * this.voteOptions.length);
			this.voteOptions[idx].votes += 1;
			if (this.demoTab === "voting") this.renderDemo();
		};
		const scheduleNext = () => {
			const delay = 1200 + Math.random() * 2000;
			this.simTimer = window.setTimeout(() => {
				tick();
				scheduleNext();
			}, delay) as unknown as number;
		};
		scheduleNext();
	}

	private renderDemo() {
		const tabs: { key: "spider" | "ranking" | "voting"; label: string; icon: string }[] = [
			{ key: "spider", label: "Spider Chart", icon: "🕸" },
			{ key: "ranking", label: "Ranking", icon: "📊" },
			{ key: "voting", label: "Live Voting", icon: "☑" },
		];

		let content = "";
		if (this.demoTab === "spider") content = this.renderSpider();
		else if (this.demoTab === "ranking") content = this.renderRanking();
		else content = this.renderVoting();

		this.shadow.innerHTML = `
		<style>
			:host { display: block; padding: 1.5rem; }
			.rapp-nav { display: flex; gap: 8px; align-items: center; margin-bottom: 1rem; min-height: 36px; }
			.rapp-nav__title { font-size: 15px; font-weight: 600; flex: 1; color: #e2e8f0; }
			.demo-badge { font-size: 0.7rem; padding: 2px 8px; border-radius: 999px; background: #6366f1; color: #fff; font-weight: 500; }

			/* Tabs */
			.demo-tabs { display: flex; gap: 4px; margin-bottom: 1.5rem; background: #0f172a; border-radius: 10px; padding: 4px; }
			.demo-tab { flex: 1; text-align: center; padding: 0.6rem 0.75rem; border-radius: 8px; border: none; background: transparent; color: #94a3b8; cursor: pointer; font-size: 0.875rem; font-family: inherit; transition: all 0.15s; }
			.demo-tab:hover { color: #e2e8f0; background: #1e293b; }
			.demo-tab.active { background: #1e293b; color: #e2e8f0; box-shadow: 0 1px 3px rgba(0,0,0,0.3); }
			.demo-tab-icon { margin-right: 6px; }

			/* Spider chart */
			.spider-wrap { display: flex; flex-direction: column; align-items: center; }
			.spider-svg { width: 100%; max-width: 420px; }
			.spider-legend { display: flex; gap: 1.25rem; margin-top: 1rem; justify-content: center; flex-wrap: wrap; }
			.spider-legend-item { display: flex; align-items: center; gap: 6px; cursor: pointer; padding: 4px 10px; border-radius: 6px; transition: background 0.15s; font-size: 0.875rem; color: #e2e8f0; }
			.spider-legend-item:hover { background: #1e293b; }
			.spider-legend-dot { width: 10px; height: 10px; border-radius: 50%; }
			.spider-axis-label { fill: #94a3b8; font-size: 13px; font-family: inherit; }

			/* Ranking */
			.rank-list { list-style: none; padding: 0; margin: 0; max-width: 440px; margin-inline: auto; }
			.rank-item { display: flex; align-items: center; gap: 12px; padding: 0.75rem 1rem; margin-bottom: 6px; background: #1e293b; border: 1px solid #334155; border-radius: 10px; cursor: grab; transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s; user-select: none; }
			.rank-item:active { cursor: grabbing; }
			.rank-item.dragging { opacity: 0.4; transform: scale(0.97); }
			.rank-item.drag-over { border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,0.3); }
			.rank-pos { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.8rem; color: #0f172a; flex-shrink: 0; }
			.rank-pos.gold { background: #f59e0b; }
			.rank-pos.silver { background: #94a3b8; }
			.rank-pos.bronze { background: #cd7f32; }
			.rank-pos.plain { background: #334155; color: #94a3b8; }
			.rank-emoji { font-size: 1.5rem; flex-shrink: 0; }
			.rank-name { flex: 1; color: #f1f5f9; font-weight: 600; font-size: 1rem; }
			.rank-grip { color: #475569; font-size: 1.1rem; flex-shrink: 0; letter-spacing: 2px; }

			/* Voting */
			.vote-wrap { max-width: 480px; margin-inline: auto; }
			.vote-option { display: flex; align-items: center; gap: 12px; padding: 0.75rem 1rem; margin-bottom: 8px; background: #1e293b; border: 1px solid #334155; border-radius: 10px; cursor: pointer; position: relative; overflow: hidden; transition: border-color 0.15s; }
			.vote-option:hover { border-color: #6366f1; }
			.vote-option.voted { border-color: #6366f1; }
			.vote-fill { position: absolute; left: 0; top: 0; bottom: 0; opacity: 0.12; transition: width 0.7s ease-out; pointer-events: none; }
			.vote-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; position: relative; z-index: 1; }
			.vote-name { flex: 1; color: #f1f5f9; font-weight: 600; font-size: 1rem; position: relative; z-index: 1; }
			.vote-count { color: #94a3b8; font-weight: 400; font-size: 0.8rem; min-width: 24px; text-align: right; position: relative; z-index: 1; font-variant-numeric: tabular-nums; }
			.vote-pct { font-weight: 600; font-size: 0.8rem; min-width: 40px; text-align: right; position: relative; z-index: 1; font-variant-numeric: tabular-nums; }
			.vote-badge { font-size: 0.625rem; padding: 2px 6px; border-radius: 999px; background: rgba(255,255,255,0.05); color: #94a3b8; margin-left: 6px; position: relative; z-index: 1; font-weight: 400; }
			.vote-actions { display: flex; justify-content: center; margin-top: 1rem; }
			.vote-reset { padding: 0.5rem 1.25rem; border-radius: 8px; border: 1px solid #334155; background: #1e293b; color: #94a3b8; cursor: pointer; font-size: 0.875rem; font-family: inherit; transition: all 0.15s; }
			.vote-reset:hover { border-color: #ef4444; color: #fca5a5; }
			.vote-status { text-align: center; margin-bottom: 1rem; font-size: 0.8rem; color: #64748b; }
		</style>

		<div class="rapp-nav">
			<span class="rapp-nav__title">Choices</span>
			<span class="demo-badge">DEMO</span>
		</div>

		<div class="demo-tabs">
			${tabs.map((t) => `<button class="demo-tab${this.demoTab === t.key ? " active" : ""}" data-tab="${t.key}"><span class="demo-tab-icon">${t.icon}</span>${this.esc(t.label)}</button>`).join("")}
		</div>

		<div class="demo-content">
			${content}
		</div>
		`;

		this.bindDemoEvents();
	}

	/* -- Spider Chart -- */

	private polarToXY(cx: number, cy: number, radius: number, angleDeg: number): { x: number; y: number } {
		const rad = ((angleDeg - 90) * Math.PI) / 180;
		return { x: cx + radius * Math.cos(rad), y: cy + radius * Math.sin(rad) };
	}

	private renderSpider(): string {
		const cx = 200, cy = 200, maxR = 150;
		const axes = ["Taste", "Price", "Speed", "Healthy", "Distance"];
		const people: { name: string; color: string; values: number[] }[] = [
			{ name: "Alice", color: "#7c5bf5", values: [0.9, 0.6, 0.8, 0.4, 0.7] },
			{ name: "Bob", color: "#f59e0b", values: [0.5, 0.9, 0.6, 0.7, 0.8] },
			{ name: "Carol", color: "#10b981", values: [0.7, 0.4, 0.9, 0.8, 0.3] },
		];
		const angleStep = 360 / axes.length;

		// Grid rings
		let gridLines = "";
		for (let ring = 1; ring <= 5; ring++) {
			const r = (ring / 5) * maxR;
			const pts = axes.map((_, i) => {
				const p = this.polarToXY(cx, cy, r, i * angleStep);
				return `${p.x},${p.y}`;
			}).join(" ");
			gridLines += `<polygon points="${pts}" fill="none" stroke="#334155" stroke-width="1"/>`;
		}

		// Axis lines + labels
		let axisLines = "";
		const labelOffset = 18;
		axes.forEach((label, i) => {
			const angle = i * angleStep;
			const tip = this.polarToXY(cx, cy, maxR, angle);
			axisLines += `<line x1="${cx}" y1="${cy}" x2="${tip.x}" y2="${tip.y}" stroke="#334155" stroke-width="1"/>`;
			const lp = this.polarToXY(cx, cy, maxR + labelOffset, angle);
			axisLines += `<text x="${lp.x}" y="${lp.y}" text-anchor="middle" dominant-baseline="central" class="spider-axis-label">${this.esc(label)}</text>`;
		});

		// Data polygons
		let polygons = "";
		people.forEach((person) => {
			const dimmed = this.hoveredPerson !== null && this.hoveredPerson !== person.name;
			const opacity = dimmed ? 0.12 : 0.25;
			const strokeOpacity = dimmed ? 0.2 : 1;
			const strokeWidth = dimmed ? 1 : 2;
			const pts = person.values.map((v, i) => {
				const p = this.polarToXY(cx, cy, v * maxR, i * angleStep);
				return `${p.x},${p.y}`;
			}).join(" ");
			polygons += `<polygon points="${pts}" fill="${person.color}" fill-opacity="${opacity}" stroke="${person.color}" stroke-opacity="${strokeOpacity}" stroke-width="${strokeWidth}" stroke-linejoin="round"/>`;

			// Dots at each vertex
			person.values.forEach((v, i) => {
				const p = this.polarToXY(cx, cy, v * maxR, i * angleStep);
				const dotOpacity = dimmed ? 0.2 : 1;
				polygons += `<circle cx="${p.x}" cy="${p.y}" r="4" fill="${person.color}" opacity="${dotOpacity}"/>`;
			});
		});

		const legend = people.map((p) =>
			`<div class="spider-legend-item" data-person="${this.esc(p.name)}"><span class="spider-legend-dot" style="background:${p.color}"></span>${this.esc(p.name)}</div>`
		).join("");

		return `<div class="spider-wrap">
			<svg class="spider-svg" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
				${gridLines}
				${axisLines}
				${polygons}
			</svg>
			<div class="spider-legend">${legend}</div>
		</div>`;
	}

	/* -- Ranking -- */

	private renderRanking(): string {
		const medalClass = (i: number) => i === 0 ? "gold" : i === 1 ? "silver" : i === 2 ? "bronze" : "plain";
		const items = this.rankItems.map((item, i) =>
			`<li class="rank-item" draggable="true" data-rank-id="${item.id}">
				<span class="rank-pos ${medalClass(i)}">${i + 1}</span>
				<span class="rank-emoji">${item.emoji}</span>
				<span class="rank-name">${this.esc(item.name)}</span>
				<span class="rank-grip">⠿</span>
			</li>`
		).join("");
		return `<ul class="rank-list">${items}</ul>`;
	}

	/* -- Live Voting -- */

	private renderVoting(): string {
		const sorted = [...this.voteOptions].sort((a, b) => b.votes - a.votes);
		const total = sorted.reduce((s, o) => s + o.votes, 0);
		const maxVotes = Math.max(...sorted.map((o) => o.votes), 1);

		const items = sorted.map((opt) => {
			const pct = total > 0 ? (opt.votes / total) * 100 : 0;
			const isLeader = opt.votes === maxVotes && total > 4;
			return `<div class="vote-option${this.voted ? " voted" : ""}" data-vote-id="${opt.id}" style="border-color:${this.voted === true ? (this.votedId === opt.id ? opt.color : '#334155') : '#334155'}">
				<div class="vote-fill" style="width:${pct}%;background:${opt.color}"></div>
				<span class="vote-dot" style="background:${opt.color}"></span>
				<span class="vote-name">${this.esc(opt.name)}${isLeader ? `<span class="vote-badge">leading</span>` : ""}</span>
				<span class="vote-count">${opt.votes}</span>
				<span class="vote-pct" style="color:${opt.color}">${pct.toFixed(0)}%</span>
			</div>`;
		}).join("");

		const status = this.voted
			? "Results are in!"
			: "Pick a movie \u2014 votes update live";

		return `<div class="vote-wrap">
			<div class="vote-status">${status}</div>
			${items}
			${this.voted ? `<div class="vote-actions"><button class="vote-reset">Reset demo</button></div>` : ""}
		</div>`;
	}

	/* -- Demo event binding -- */

	private bindDemoEvents() {
		// Tab switching
		this.shadow.querySelectorAll<HTMLButtonElement>(".demo-tab").forEach((btn) => {
			btn.addEventListener("click", () => {
				const tab = btn.dataset.tab as "spider" | "ranking" | "voting";
				if (tab && tab !== this.demoTab) {
					this.demoTab = tab;
					this.renderDemo();
				}
			});
		});

		// Spider legend hover
		this.shadow.querySelectorAll<HTMLElement>(".spider-legend-item").forEach((el) => {
			el.addEventListener("mouseenter", () => {
				this.hoveredPerson = el.dataset.person || null;
				this.renderDemo();
			});
			el.addEventListener("mouseleave", () => {
				this.hoveredPerson = null;
				this.renderDemo();
			});
		});

		// Ranking drag-and-drop
		const rankList = this.shadow.querySelector(".rank-list");
		if (rankList) {
			const items = rankList.querySelectorAll<HTMLLIElement>(".rank-item");
			items.forEach((li) => {
				li.addEventListener("dragstart", (e: DragEvent) => {
					const id = parseInt(li.dataset.rankId || "0", 10);
					this.rankDragging = id;
					li.classList.add("dragging");
					if (e.dataTransfer) {
						e.dataTransfer.effectAllowed = "move";
						e.dataTransfer.setData("text/plain", String(id));
					}
				});

				li.addEventListener("dragover", (e: DragEvent) => {
					e.preventDefault();
					if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
					li.classList.add("drag-over");
				});

				li.addEventListener("dragleave", () => {
					li.classList.remove("drag-over");
				});

				li.addEventListener("drop", (e: DragEvent) => {
					e.preventDefault();
					li.classList.remove("drag-over");
					const targetId = parseInt(li.dataset.rankId || "0", 10);
					if (this.rankDragging !== null && this.rankDragging !== targetId) {
						const fromIdx = this.rankItems.findIndex((r) => r.id === this.rankDragging);
						const toIdx = this.rankItems.findIndex((r) => r.id === targetId);
						if (fromIdx !== -1 && toIdx !== -1) {
							const [moved] = this.rankItems.splice(fromIdx, 1);
							this.rankItems.splice(toIdx, 0, moved);
							this.renderDemo();
						}
					}
				});

				li.addEventListener("dragend", () => {
					this.rankDragging = null;
					li.classList.remove("dragging");
				});
			});
		}

		// Voting click
		this.shadow.querySelectorAll<HTMLElement>(".vote-option").forEach((el) => {
			el.addEventListener("click", () => {
				if (this.voted) return;
				const id = el.dataset.voteId || "";
				const opt = this.voteOptions.find((o) => o.id === id);
				if (opt) {
					opt.votes += 1;
					this.voted = true;
					this.votedId = id;
					this.renderDemo();
				}
			});
		});

		// Vote reset
		const resetBtn = this.shadow.querySelector<HTMLButtonElement>(".vote-reset");
		if (resetBtn) {
			resetBtn.addEventListener("click", () => {
				this.voteOptions = [
					{ id: "action", name: "Action Movie", color: "#ef4444", votes: 2 },
					{ id: "comedy", name: "Comedy", color: "#f59e0b", votes: 3 },
					{ id: "horror", name: "Horror", color: "#8b5cf6", votes: 1 },
					{ id: "scifi", name: "Sci-Fi", color: "#06b6d4", votes: 2 },
				];
				this.voted = false;
				this.votedId = null;
				this.startVoteSim();
				this.renderDemo();
			});
		}
	}

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

customElements.define("folk-choices-dashboard", FolkChoicesDashboard);
