/**
 * <folk-tasks-board> — kanban board for workspace task management.
 *
 * Views: workspace list → board with draggable columns.
 * Supports task creation, status changes, and priority labels.
 */

import { boardSchema, type BoardDoc } from "../schemas";
import type { DocumentId } from "../../../shared/local-first/document";
import { TourEngine } from "../../../shared/tour-engine";
import { ViewHistory } from "../../../shared/view-history.js";

class FolkTasksBoard extends HTMLElement {
	private shadow: ShadowRoot;
	private space = "";
	private view: "list" | "board" = "list";
	private workspaceSlug = "";
	private workspaces: any[] = [];
	private tasks: any[] = [];
	private statuses: string[] = ["TODO", "IN_PROGRESS", "REVIEW", "DONE"];
	private loading = false;
	private error = "";
	private isDemo = false;
	private dragTaskId: string | null = null;
	private editingTaskId: string | null = null;
	private showCreateForm = false;
	private priorities = ["LOW", "MEDIUM", "HIGH", "URGENT"];
	private _offlineUnsubs: (() => void)[] = [];
	private _history = new ViewHistory<"list" | "board">("list");
	private _tour!: TourEngine;
	private static readonly TOUR_STEPS = [
		{ target: '.workspace-card', title: "Workspaces", message: "Select a workspace to open its kanban board.", advanceOnClick: true },
		{ target: '#create-task', title: "New Task", message: "Create a new task with title, priority, and description.", advanceOnClick: false },
		{ target: '.board', title: "Kanban Board", message: "Drag tasks between columns — TODO, In Progress, Review, Done.", advanceOnClick: false },
		{ target: '.badge.clickable', title: "Priority", message: "Click the priority badge on a task to cycle through levels.", advanceOnClick: false },
	];

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

	connectedCallback() {
		this.space = this.getAttribute("space") || "demo";
		if (this.space === "demo") { this.loadDemoData(); }
		else {
			this.subscribeOffline();
			this.loadWorkspaces();
			this.render();
		}
		if (!localStorage.getItem("rtasks_tour_done")) {
			setTimeout(() => this._tour.start(), 1200);
		}
	}

	disconnectedCallback() {
		for (const unsub of this._offlineUnsubs) unsub();
		this._offlineUnsubs = [];
	}

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

		try {
			const docs = await runtime.subscribeModule('tasks', 'boards', boardSchema);
			// Build workspace list from cached boards
			if (docs.size > 0 && this.workspaces.length === 0) {
				const boards: any[] = [];
				for (const [docId, doc] of docs) {
					const d = doc as BoardDoc;
					if (!d?.board) continue;
					boards.push({ slug: d.board.slug, name: d.board.name, icon: null, task_count: Object.keys(d.tasks || {}).length });
					this._offlineUnsubs.push(runtime.onChange(docId, () => this.refreshFromDocs()));
				}
				if (boards.length > 0) {
					this.workspaces = boards;
					this.render();
				}
			}
		} catch { /* runtime unavailable */ }
	}

	private refreshFromDocs() {
		const runtime = (window as any).__rspaceOfflineRuntime;
		if (!runtime || !this.workspaceSlug) return;
		// Reload tasks for current board from runtime
		const docId = runtime.makeDocId('tasks', 'boards', this.workspaceSlug);
		const doc = runtime.get(docId) as BoardDoc | undefined;
		if (doc?.tasks && Object.keys(doc.tasks).length > 0) {
			this.tasks = Object.values(doc.tasks).map(t => ({
				id: t.id, title: t.title, description: t.description,
				status: t.status, priority: t.priority, labels: t.labels,
				assignee: t.assigneeId,
			}));
			this.render();
		}
	}

	private loadDemoData() {
		this.isDemo = true;
		this.workspaces = [{ slug: "rspace-dev", name: "rSpace Development", icon: "\u{1F680}", task_count: 11, member_count: 2 }];
		this.view = "board";
		this.workspaceSlug = "rspace-dev";
		this.tasks = [
			{ id: "d1", title: "Add dark mode toggle to settings page", status: "TODO", priority: "MEDIUM", labels: ["feature"], assignee: "Alice" },
			{ id: "d2", title: "Write API documentation for rPubs endpoints", status: "TODO", priority: "LOW", labels: ["docs"], assignee: "Bob" },
			{ id: "d3", title: "Investigate slow PDF generation on large documents", status: "TODO", priority: "HIGH", labels: ["bug"], assignee: "Alice" },
			{ id: "d4", title: "Implement file search and filtering in rFiles", status: "IN_PROGRESS", priority: "HIGH", labels: ["feature"], assignee: "Alice" },
			{ id: "d5", title: "Set up SMTP relay for transactional notifications", status: "IN_PROGRESS", priority: "MEDIUM", labels: ["chore"], assignee: "Bob" },
			{ id: "d6", title: "Add PDF export to rNotes notebooks", status: "REVIEW", priority: "MEDIUM", labels: ["feature"], assignee: "Bob" },
			{ id: "d7", title: "Fix conviction score decay calculation in rVote", status: "REVIEW", priority: "HIGH", labels: ["bug"], assignee: "Alice" },
			{ id: "d8", title: "Deploy EncryptID passkey authentication", status: "DONE", priority: "URGENT", labels: ["feature"], assignee: "Alice" },
			{ id: "d9", title: "Set up Cloudflare tunnel for all r* domains", status: "DONE", priority: "HIGH", labels: ["chore"], assignee: "Bob" },
			{ id: "d10", title: "Create cosmolocal provider directory with 6 printers", status: "DONE", priority: "MEDIUM", labels: ["feature"], assignee: "Alice" },
			{ id: "d11", title: "Migrate email from Resend to self-hosted Mailcow", status: "DONE", priority: "MEDIUM", labels: ["chore"], assignee: "Bob" },
		];
		this.render();
	}

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

	private async loadWorkspaces() {
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/spaces`);
			if (res.ok) this.workspaces = await res.json();
		} catch { this.workspaces = []; }
		this.render();
	}

	private async loadTasks() {
		if (!this.workspaceSlug) return;
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/spaces/${this.workspaceSlug}/tasks`);
			if (res.ok) this.tasks = await res.json();

			const spaceRes = await fetch(`${base}/api/spaces/${this.workspaceSlug}`);
			if (spaceRes.ok) {
				const space = await spaceRes.json();
				if (space.statuses?.length) this.statuses = space.statuses;
			}
		} catch { this.tasks = []; }
		this.render();
	}

	private async createWorkspace() {
		const name = prompt("Workspace name:");
		if (!name?.trim()) return;
		if (this.isDemo) {
			const slug = name.trim().toLowerCase().replace(/\s+/g, "-");
			this.workspaces.push({ slug, name: name.trim(), icon: "\u{1F4CB}", task_count: 0, member_count: 1 });
			this.render();
			return;
		}
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/spaces`, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ name: name.trim() }),
			});
			if (res.ok) this.loadWorkspaces();
		} catch { this.error = "Failed to create workspace"; this.render(); }
	}

	private async submitCreateTask(title: string, priority: string, description: string) {
		if (!title.trim()) return;
		if (this.isDemo) {
			this.tasks.push({ id: `d${Date.now()}`, title: title.trim(), status: "TODO", priority, labels: [], description: description.trim() || undefined });
			this.showCreateForm = false;
			this.render();
			return;
		}
		try {
			const base = this.getApiBase();
			await fetch(`${base}/api/spaces/${this.workspaceSlug}/tasks`, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ title: title.trim(), priority, description: description.trim() || undefined }),
			});
			this.showCreateForm = false;
			this.loadTasks();
		} catch { this.error = "Failed to create task"; this.render(); }
	}

	private async updateTask(taskId: string, fields: Record<string, string>) {
		if (this.isDemo) {
			const task = this.tasks.find(t => t.id === taskId);
			if (task) Object.assign(task, fields);
			this.editingTaskId = null;
			this.render();
			return;
		}
		try {
			const base = this.getApiBase();
			await fetch(`${base}/api/tasks/${taskId}`, {
				method: "PATCH",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify(fields),
			});
			this.editingTaskId = null;
			this.loadTasks();
		} catch { this.error = "Failed to update task"; this.render(); }
	}

	private cyclePriority(taskId: string) {
		const task = this.tasks.find(t => t.id === taskId);
		if (!task) return;
		const idx = this.priorities.indexOf(task.priority || "MEDIUM");
		const next = this.priorities[(idx + 1) % this.priorities.length];
		this.updateTask(taskId, { priority: next });
	}

	private async moveTask(taskId: string, newStatus: string) {
		if (this.isDemo) {
			const task = this.tasks.find(t => t.id === taskId);
			if (task) { task.status = newStatus; this.render(); }
			return;
		}
		try {
			const base = this.getApiBase();
			await fetch(`${base}/api/tasks/${taskId}`, {
				method: "PATCH",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ status: newStatus }),
			});
			this.loadTasks();
		} catch { this.error = "Failed to move task"; this.render(); }
	}

	private openBoard(slug: string) {
		this.workspaceSlug = slug;
		this.view = "board";
		this.loadTasks();
	}

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

	private render() {
		this.shadow.innerHTML = `
		<style>
			:host { display: block; font-family: system-ui, -apple-system, sans-serif; color: var(--rs-text-primary); }
			* { box-sizing: border-box; }

			.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-subtle); background: transparent; color: var(--rs-text-secondary); cursor: pointer; font-size: 13px; text-decoration: none; }
			.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); }

			.workspace-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
			.workspace-card {
				background: var(--rs-bg-surface); border: 1px solid var(--rs-border-strong); border-radius: 10px;
				padding: 16px; cursor: pointer; transition: border-color 0.2s;
			}
			.workspace-card:hover { border-color: var(--rs-border-strong); }
			.ws-name { font-size: 15px; font-weight: 600; margin-bottom: 4px; }
			.ws-meta { font-size: 12px; color: var(--rs-text-muted); }

			.board { display: flex; gap: 12px; overflow-x: auto; min-height: 400px; padding-bottom: 12px; }
			.column {
				min-width: 240px; max-width: 280px; flex-shrink: 0;
				background: var(--rs-bg-surface-sunken); border: 1px solid var(--rs-border); border-radius: 10px; padding: 12px;
			}
			.col-header { font-size: 13px; font-weight: 600; text-transform: uppercase; color: var(--rs-text-muted); margin-bottom: 10px; display: flex; justify-content: space-between; }
			.col-count { background: var(--rs-border); border-radius: 10px; padding: 0 8px; font-size: 11px; }

			.column.drag-over { background: var(--rs-bg-surface); border-color: var(--rs-primary); }

			.task-card {
				background: var(--rs-bg-surface); border: 1px solid var(--rs-border-strong); border-radius: 8px;
				padding: 10px 12px; margin-bottom: 8px; cursor: grab;
				transition: opacity 0.2s;
			}
			.task-card.dragging { opacity: 0.4; }
			.task-card:hover { border-color: var(--rs-border-strong); }
			.task-title { font-size: 13px; font-weight: 500; margin-bottom: 4px; }
			.task-meta { display: flex; gap: 6px; flex-wrap: wrap; }
			.badge { font-size: 10px; padding: 2px 6px; border-radius: 4px; background: var(--rs-border); color: var(--rs-text-muted); }
			.badge-urgent { background: #3b1111; color: #f87171; }
			.badge-high { background: #3b2611; color: #fb923c; }
			.badge-medium { background: #3b3511; color: #facc15; }
			.badge-low { background: #112a3b; color: #60a5fa; }

			.move-btns { display: flex; gap: 4px; margin-top: 6px; }
			.move-btn { font-size: 10px; padding: 2px 6px; border-radius: 4px; border: 1px solid var(--rs-border-strong); background: var(--rs-bg-surface-sunken); color: var(--rs-text-muted); cursor: pointer; }
			.move-btn:hover { border-color: var(--rs-border-strong); color: var(--rs-text-secondary); }

			.create-form { background: var(--rs-bg-surface); border: 1px solid var(--rs-primary); border-radius: 8px; padding: 10px; margin-bottom: 10px; }
			.create-form input, .create-form select, .create-form textarea {
				width: 100%; padding: 6px 8px; border-radius: 6px; border: 1px solid var(--rs-border-strong);
				background: var(--rs-bg-surface-sunken); color: var(--rs-text-primary); font-size: 13px; margin-bottom: 6px; outline: none; font-family: inherit;
			}
			.create-form input:focus, .create-form select:focus, .create-form textarea:focus { border-color: var(--rs-primary-hover); }
			.create-form textarea { resize: vertical; min-height: 40px; }
			.create-form-actions { display: flex; gap: 6px; }
			.create-form-actions button { padding: 4px 12px; border-radius: 6px; border: none; font-size: 12px; cursor: pointer; font-weight: 600; }
			.cf-submit { background: var(--rs-primary); color: #fff; }
			.cf-cancel { background: transparent; color: var(--rs-text-muted); border: 1px solid var(--rs-border-strong) !important; }

			.task-title-input {
				width: 100%; padding: 4px 6px; border-radius: 4px; border: 1px solid var(--rs-primary-hover);
				background: var(--rs-bg-surface-sunken); color: var(--rs-text-primary); font-size: 13px; font-weight: 500; outline: none; font-family: inherit;
			}
			.badge.clickable { cursor: pointer; transition: all 0.15s; }
			.badge.clickable:hover { filter: brightness(1.3); transform: scale(1.1); }

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

			@media (max-width: 768px) {
				.board { flex-direction: column; overflow-x: visible; }
				.column { min-width: 100%; max-width: 100%; }
			}
		</style>

		${this.error ? `<div style="color:var(--rs-error);text-align:center;padding:8px">${this.esc(this.error)}</div>` : ""}
		${this.view === "list" ? this.renderList() : this.renderBoard()}
		`;
		this.attachListeners();
		this._tour.renderOverlay();
	}

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

	private renderList(): string {
		return `
			<div class="rapp-nav">
				<span class="rapp-nav__title">Workspaces</span>
				<button class="rapp-nav__btn" id="create-ws">+ New Workspace</button>
				<button class="rapp-nav__btn" id="btn-tour" style="font-size:0.78rem;padding:4px 10px;opacity:0.7">Tour</button>
			</div>
			${this.workspaces.length > 0 ? `<div class="workspace-grid">
				${this.workspaces.map(ws => `
					<div class="workspace-card" data-ws="${ws.slug}">
						<div class="ws-name">${this.esc(ws.icon || "📋")} ${this.esc(ws.name)}</div>
						<div class="ws-meta">${ws.task_count || 0} tasks · ${ws.member_count || 0} members</div>
					</div>
				`).join("")}
			</div>` : `<div class="empty">
				<p style="font-size:16px;margin-bottom:8px">No workspaces yet</p>
				<p style="font-size:13px">Create a workspace to start managing tasks</p>
			</div>`}
		`;
	}

	private renderCreateForm(): string {
		if (!this.showCreateForm) return "";
		return `
			<div class="create-form" id="create-form">
				<input type="text" id="cf-title" placeholder="Task title..." autofocus>
				<select id="cf-priority">
					<option value="LOW">Low</option>
					<option value="MEDIUM" selected>Medium</option>
					<option value="HIGH">High</option>
					<option value="URGENT">Urgent</option>
				</select>
				<textarea id="cf-desc" placeholder="Description (optional)" rows="2"></textarea>
				<div class="create-form-actions">
					<button class="cf-submit" id="cf-submit">Add Task</button>
					<button class="cf-cancel" id="cf-cancel">Cancel</button>
				</div>
			</div>`;
	}

	private renderBoard(): string {
		return `
			<div class="rapp-nav">
				${this._history.canGoBack ? '<button class="rapp-nav__back" data-back="list">\u2190 Workspaces</button>' : ''}
				<span class="rapp-nav__title">${this.esc(this.workspaceSlug)}</span>
				<button class="rapp-nav__btn" id="create-task">+ New Task</button>
			</div>
			<div class="board">
				${this.statuses.map(status => {
					const columnTasks = this.tasks.filter(t => t.status === status);
					return `
						<div class="column" data-status="${status}">
							<div class="col-header">
								<span>${this.esc(status.replace(/_/g, " "))}</span>
								<span class="col-count">${columnTasks.length}</span>
							</div>
							${status === "TODO" ? this.renderCreateForm() : ""}
							${columnTasks.map(t => this.renderTaskCard(t, status)).join("")}
						</div>
					`;
				}).join("")}
			</div>
		`;
	}

	private renderTaskCard(task: any, currentStatus: string): string {
		const otherStatuses = this.statuses.filter(s => s !== currentStatus);
		const isEditing = this.editingTaskId === task.id;
		const priorityBadge = (p: string) => {
			const map: Record<string, string> = { URGENT: "badge-urgent", HIGH: "badge-high", MEDIUM: "badge-medium", LOW: "badge-low" };
			return map[p] ? `<span class="badge clickable ${map[p]}" data-cycle-priority="${task.id}">${this.esc(p.toLowerCase())}</span>` : "";
		};
		return `
			<div class="task-card" draggable="${isEditing ? "false" : "true"}" data-task-id="${task.id}" data-collab-id="task:${task.id}">
				${isEditing
					? `<input class="task-title-input" data-edit-title="${task.id}" value="${this.esc(task.title)}">`
					: `<div class="task-title" data-start-edit="${task.id}" style="cursor:text">${this.esc(task.title)}</div>`}
				<div class="task-meta">
					${priorityBadge(task.priority || "")}
					${(task.labels || []).map((l: string) => `<span class="badge">${this.esc(l)}</span>`).join("")}
				</div>
				${task.assignee ? `<div style="font-size:11px;color:var(--rs-text-muted);margin-top:4px">${this.esc(task.assignee)}</div>` : ""}
				<div class="move-btns">
					${otherStatuses.map(s => `<button class="move-btn" data-move="${task.id}" data-to="${s}">\u2192 ${this.esc(s.replace(/_/g, " ").substring(0, 8))}</button>`).join("")}
				</div>
			</div>
		`;
	}

	private attachListeners() {
		this.shadow.querySelector("#btn-tour")?.addEventListener("click", () => this.startTour());
		this.shadow.getElementById("create-ws")?.addEventListener("click", () => this.createWorkspace());
		this.shadow.getElementById("create-task")?.addEventListener("click", () => {
			this.showCreateForm = !this.showCreateForm;
			this.render();
			if (this.showCreateForm) {
				setTimeout(() => this.shadow.getElementById("cf-title")?.focus(), 0);
			}
		});

		// Create form handlers
		this.shadow.getElementById("cf-submit")?.addEventListener("click", () => {
			const title = (this.shadow.getElementById("cf-title") as HTMLInputElement)?.value || "";
			const priority = (this.shadow.getElementById("cf-priority") as HTMLSelectElement)?.value || "MEDIUM";
			const desc = (this.shadow.getElementById("cf-desc") as HTMLTextAreaElement)?.value || "";
			this.submitCreateTask(title, priority, desc);
		});
		this.shadow.getElementById("cf-cancel")?.addEventListener("click", () => {
			this.showCreateForm = false; this.render();
		});
		this.shadow.getElementById("cf-title")?.addEventListener("keydown", (e) => {
			if ((e as KeyboardEvent).key === "Enter") {
				const title = (this.shadow.getElementById("cf-title") as HTMLInputElement)?.value || "";
				const priority = (this.shadow.getElementById("cf-priority") as HTMLSelectElement)?.value || "MEDIUM";
				const desc = (this.shadow.getElementById("cf-desc") as HTMLTextAreaElement)?.value || "";
				this.submitCreateTask(title, priority, desc);
			}
		});

		// Inline title editing
		this.shadow.querySelectorAll("[data-start-edit]").forEach(el => {
			el.addEventListener("click", (e) => {
				e.stopPropagation();
				this.editingTaskId = (el as HTMLElement).dataset.startEdit!;
				this.render();
				setTimeout(() => {
					const input = this.shadow.querySelector(`[data-edit-title="${this.editingTaskId}"]`) as HTMLInputElement;
					if (input) { input.focus(); input.select(); }
				}, 0);
			});
		});
		this.shadow.querySelectorAll("[data-edit-title]").forEach(el => {
			const handler = () => {
				const taskId = (el as HTMLElement).dataset.editTitle!;
				const val = (el as HTMLInputElement).value;
				if (val.trim()) this.updateTask(taskId, { title: val.trim() });
				else { this.editingTaskId = null; this.render(); }
			};
			el.addEventListener("blur", handler);
			el.addEventListener("keydown", (e) => {
				if ((e as KeyboardEvent).key === "Enter") handler();
				if ((e as KeyboardEvent).key === "Escape") { this.editingTaskId = null; this.render(); }
			});
		});

		// Priority cycling
		this.shadow.querySelectorAll("[data-cycle-priority]").forEach(el => {
			el.addEventListener("click", (e) => {
				e.stopPropagation();
				this.cyclePriority((el as HTMLElement).dataset.cyclePriority!);
			});
		});

		this.shadow.querySelectorAll("[data-ws]").forEach(el => {
			el.addEventListener("click", () => {
				this._history.push("list");
				this._history.push("board", { ws: (el as HTMLElement).dataset.ws });
				this.openBoard((el as HTMLElement).dataset.ws!);
			});
		});
		this.shadow.querySelectorAll("[data-back]").forEach(el => {
			el.addEventListener("click", () => this.goBack());
		});
		this.shadow.querySelectorAll("[data-move]").forEach(el => {
			el.addEventListener("click", (e) => {
				e.stopPropagation();
				const btn = el as HTMLElement;
				this.moveTask(btn.dataset.move!, btn.dataset.to!);
			});
		});

		// HTML5 drag-and-drop on task cards
		this.shadow.querySelectorAll(".task-card[draggable]").forEach(card => {
			card.addEventListener("dragstart", (e) => {
				const el = card as HTMLElement;
				this.dragTaskId = el.dataset.taskId || null;
				el.classList.add("dragging");
				const dt = (e as DragEvent).dataTransfer;
				if (dt && this.dragTaskId) {
					const task = this.tasks.find(t => t.id === this.dragTaskId);
					dt.setData("text/plain", task?.title || this.dragTaskId);
					dt.setData("application/rspace-item", JSON.stringify({
						module: "rtasks",
						entityId: this.dragTaskId,
						title: task?.title || "",
						label: "rTasks",
						color: "#f97316",
					}));
				}
			});
			card.addEventListener("dragend", () => {
				(card as HTMLElement).classList.remove("dragging");
				this.dragTaskId = null;
			});
		});

		this.shadow.querySelectorAll(".column[data-status]").forEach(col => {
			col.addEventListener("dragover", (e) => {
				e.preventDefault();
				(col as HTMLElement).classList.add("drag-over");
			});
			col.addEventListener("dragleave", () => {
				(col as HTMLElement).classList.remove("drag-over");
			});
			col.addEventListener("drop", (e) => {
				e.preventDefault();
				(col as HTMLElement).classList.remove("drag-over");
				const status = (col as HTMLElement).dataset.status!;
				if (this.dragTaskId) {
					this.moveTask(this.dragTaskId, status);
					this.dragTaskId = null;
				}
			});
		});
	}

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

customElements.define("folk-tasks-board", FolkTasksBoard);
