/**
 * <folk-file-browser> — file browsing, upload, share links, and memory cards.
 *
 * Attributes:
 *   space="slug"   — shared space to browse (default: "default")
 */

import { filesSchema, type FilesDoc } from "../schemas";
import { makeDraggableAll } from "../../../shared/draggable";
import type { DocumentId } from "../../../shared/local-first/document";
import { TourEngine } from "../../../shared/tour-engine";
import { authFetch, requireAuth } from "../../../shared/auth-fetch";
import { startPresenceHeartbeat } from '../../../shared/collab-presence';

class FolkFileBrowser extends HTMLElement {
	private shadow: ShadowRoot;
	private space = "default";
	private files: any[] = [];
	private cards: any[] = [];
	private tab: "files" | "cards" = "files";
	private loading = false;
	private _offlineUnsubs: (() => void)[] = [];
	private _stopPresence: (() => void) | null = null;
	private _tour!: TourEngine;
	private static readonly TOUR_STEPS = [
		{ target: '.tab-btn[data-tab="files"]', title: "Files Tab", message: "Browse uploaded files — download, share, or delete them.", advanceOnClick: true },
		{ target: '.tab-btn[data-tab="cards"]', title: "Memory Cards", message: "Create and manage memory cards to organise your knowledge.", advanceOnClick: true },
		{ target: '#upload-form', title: "Upload Files", message: "Upload files to your space. They're stored locally and synced when online.", advanceOnClick: false },
	];

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

	connectedCallback() {
		this.space = this.getAttribute("space") || "default";

		if (this.space === "demo") {
			this.loadDemoData();
		} else {
			this.render();
			this.subscribeOffline();
			this.loadFiles();
			this.loadCards();
		}
		if (!localStorage.getItem("rfiles_tour_done")) {
			setTimeout(() => this._tour.start(), 1200);
		}
		this._stopPresence = startPresenceHeartbeat(() => ({ module: 'rfiles', context: 'Files' }));
	}

	disconnectedCallback() {
		this._stopPresence?.();
		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('files', 'cards', filesSchema);
			for (const [docId, doc] of docs) {
				const d = doc as FilesDoc;
				if (!d) continue;

				// Populate files metadata from Automerge if REST hasn't loaded yet
				if (d.files && Object.keys(d.files).length > 0 && this.files.length === 0) {
					this.files = Object.values(d.files).map(f => ({
						id: f.id, name: f.originalFilename, original_filename: f.originalFilename,
						title: f.title || f.originalFilename, size: f.fileSize, file_size: f.fileSize,
						mime_type: f.mimeType, created_at: new Date(f.createdAt).toISOString(),
						space: this.space,
					}));
				}

				// Populate memory cards
				if (d.memoryCards && Object.keys(d.memoryCards).length > 0 && this.cards.length === 0) {
					this.cards = Object.values(d.memoryCards);
				}

				this._offlineUnsubs.push(runtime.onChange(docId, () => this.render()));
			}
			if (this.files.length > 0 || this.cards.length > 0) this.render();
		} catch { /* runtime unavailable */ }
	}

	private loadDemoData() {
		const now = Date.now();
		this.files = [
			{
				id: "demo-file-1",
				name: "meeting-notes-feb2026.md",
				original_filename: "meeting-notes-feb2026.md",
				title: "meeting-notes-feb2026.md",
				size: 12288,
				file_size: 12288,
				mime_type: "text/markdown",
				created_at: new Date(now - 3 * 86400000).toISOString(),
				updated_at: new Date(now - 1 * 86400000).toISOString(),
				space: "demo",
			},
			{
				id: "demo-file-2",
				name: "budget-proposal.pdf",
				original_filename: "budget-proposal.pdf",
				title: "budget-proposal.pdf",
				size: 2202009,
				file_size: 2202009,
				mime_type: "application/pdf",
				created_at: new Date(now - 7 * 86400000).toISOString(),
				updated_at: new Date(now - 5 * 86400000).toISOString(),
				space: "demo",
			},
			{
				id: "demo-file-3",
				name: "community-logo.svg",
				original_filename: "community-logo.svg",
				title: "community-logo.svg",
				size: 46080,
				file_size: 46080,
				mime_type: "image/svg+xml",
				created_at: new Date(now - 14 * 86400000).toISOString(),
				updated_at: new Date(now - 14 * 86400000).toISOString(),
				space: "demo",
			},
			{
				id: "demo-file-4",
				name: "workshop-recording.mp4",
				original_filename: "workshop-recording.mp4",
				title: "workshop-recording.mp4",
				size: 157286400,
				file_size: 157286400,
				mime_type: "video/mp4",
				created_at: new Date(now - 2 * 86400000).toISOString(),
				updated_at: new Date(now - 2 * 86400000).toISOString(),
				space: "demo",
			},
			{
				id: "demo-file-5",
				name: "member-directory.csv",
				original_filename: "member-directory.csv",
				title: "member-directory.csv",
				size: 8192,
				file_size: 8192,
				mime_type: "text/csv",
				created_at: new Date(now - 10 * 86400000).toISOString(),
				updated_at: new Date(now - 4 * 86400000).toISOString(),
				space: "demo",
			},
		];

		this.cards = [
			{
				id: "demo-card-1",
				title: "Design Sprint Outcomes",
				card_type: "summary",
				type: "summary",
				item_count: 3,
				body: "Key outcomes from the 5-day design sprint covering user flows, wireframes, and prototypes.",
				created_at: new Date(now - 5 * 86400000).toISOString(),
				space: "demo",
			},
			{
				id: "demo-card-2",
				title: "Q1 Budget Allocation",
				card_type: "data",
				type: "data",
				item_count: 5,
				body: "Budget breakdown across infrastructure, development, community, marketing, and reserves.",
				created_at: new Date(now - 12 * 86400000).toISOString(),
				space: "demo",
			},
			{
				id: "demo-card-3",
				title: "Community Principles",
				card_type: "reference",
				type: "reference",
				item_count: 7,
				body: "Seven guiding principles adopted by the community for governance and collaboration.",
				created_at: new Date(now - 20 * 86400000).toISOString(),
				space: "demo",
			},
		];

		this.loading = false;
		this.render();
	}

	private async loadFiles() {
		this.loading = true;
		this.render();
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/files?space=${encodeURIComponent(this.space)}`);
			const data = await res.json();
			this.files = data.files || [];
		} catch (e) {
			console.error("[FileBrowser] Error loading files:", e);
		}
		this.loading = false;
		this.render();
	}

	private async loadCards() {
		try {
			const base = this.getApiBase();
			const res = await fetch(`${base}/api/cards?space=${encodeURIComponent(this.space)}`);
			const data = await res.json();
			this.cards = data.cards || [];
		} catch {
			this.cards = [];
		}
	}

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

	private formatSize(bytes: number): string {
		if (bytes < 1024) return `${bytes} B`;
		if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
		if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
		return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
	}

	private formatDate(d: string): string {
		return new Date(d).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
	}

	private mimeIcon(mime: string): string {
		if (mime?.startsWith("image/")) return "🖼️";
		if (mime?.startsWith("video/")) return "🎥";
		if (mime?.startsWith("audio/")) return "🎵";
		if (mime?.includes("pdf")) return "📄";
		if (mime?.includes("zip") || mime?.includes("tar") || mime?.includes("gz")) return "📦";
		if (mime?.includes("text") || mime?.includes("json") || mime?.includes("xml")) return "📝";
		return "📁";
	}

	private cardTypeIcon(type: string): string {
		const icons: Record<string, string> = {
			note: "📝",
			idea: "💡",
			task: "✅",
			reference: "🔗",
			quote: "💬",
		};
		return icons[type] || "📝";
	}

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

		const fileInput = form.querySelector('input[type="file"]') as HTMLInputElement;
		if (!fileInput?.files?.length) return;

		const formData = new FormData();
		formData.append("file", fileInput.files[0]);
		formData.append("space", this.space);

		const titleInput = form.querySelector('input[name="title"]') as HTMLInputElement;
		if (titleInput?.value) formData.append("title", titleInput.value);

		try {
			const base = this.getApiBase();
			const res = await authFetch(`${base}/api/files`, { method: "POST", body: formData });
			if (res.ok) {
				form.reset();
				this.loadFiles();
			} else {
				const err = await res.json();
				alert(`Upload failed: ${err.error || "Unknown error"}`);
			}
		} catch (e) {
			alert("Upload failed — network error");
		}
	}

	private async handleDelete(fileId: string) {
		if (this.space === "demo") {
			alert("Delete is disabled in demo mode.");
			return;
		}
		if (!requireAuth("delete files")) return;
		if (!confirm("Delete this file?")) return;
		try {
			const base = this.getApiBase();
			await authFetch(`${base}/api/files/${fileId}`, { method: "DELETE" });
			this.loadFiles();
		} catch {}
	}

	private async handleShare(fileId: string) {
		if (this.space === "demo") {
			alert("Sharing is disabled in demo mode.");
			return;
		}
		if (!requireAuth("share files")) return;
		try {
			const base = this.getApiBase();
			const res = await authFetch(`${base}/api/files/${fileId}/share`, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ expires_in_hours: 72 }),
			});
			const data = await res.json();
			if (data.share?.url) {
				const fullUrl = `${window.location.origin}${this.getApiBase()}${data.share.url}`;
				await navigator.clipboard.writeText(fullUrl).catch(() => {});
				alert(`Share link copied!\n${fullUrl}\nExpires in 72 hours.`);
			}
		} catch {
			alert("Failed to create share link");
		}
	}

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

		const title = (form.querySelector('input[name="card-title"]') as HTMLInputElement)?.value;
		const body = (form.querySelector('textarea[name="card-body"]') as HTMLTextAreaElement)?.value;
		const cardType = (form.querySelector('select[name="card-type"]') as HTMLSelectElement)?.value;

		if (!title) return;

		try {
			const base = this.getApiBase();
			const res = await authFetch(`${base}/api/cards`, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({ title, body, card_type: cardType, shared_space: this.space }),
			});
			if (res.ok) {
				form.reset();
				this.loadCards();
			}
		} catch {}
	}

	private async handleDeleteCard(cardId: string) {
		if (this.space === "demo") {
			alert("Deleting cards is disabled in demo mode.");
			return;
		}
		if (!requireAuth("delete cards")) return;
		if (!confirm("Delete this card?")) return;
		try {
			const base = this.getApiBase();
			await authFetch(`${base}/api/cards/${cardId}`, { method: "DELETE" });
			this.loadCards();
		} catch {}
	}

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

			.tabs { display: flex; gap: 4px; margin-bottom: 20px; }
			.tab-btn {
				padding: 8px 20px; border: 1px solid #444; border-radius: 6px 6px 0 0;
				background: ${filesActive ? "#1a1a2e" : "#2a2a3e"}; color: #e0e0e0;
				cursor: pointer; font-size: 14px; border-bottom: ${filesActive ? "2px solid #64b5f6" : "none"};
			}
			.tab-btn:last-child {
				background: ${!filesActive ? "#1a1a2e" : "#2a2a3e"};
				border-bottom: ${!filesActive ? "2px solid #64b5f6" : "none"};
			}

			.upload-section {
				background: #1e1e2e; border: 1px dashed #555; border-radius: 8px;
				padding: 16px; margin-bottom: 20px;
			}
			.upload-section h3 { margin: 0 0 12px; font-size: 14px; color: #aaa; }
			.upload-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
			input[type="file"] { color: #ccc; font-size: 13px; }
			input[type="text"], select, textarea {
				background: #2a2a3e; border: 1px solid #444; color: #e0e0e0;
				padding: 6px 10px; border-radius: 4px; font-size: 13px;
			}
			textarea { width: 100%; min-height: 60px; resize: vertical; }
			button {
				padding: 6px 14px; border-radius: 4px; border: 1px solid #555;
				background: #2a4a7a; color: #e0e0e0; cursor: pointer; font-size: 13px;
			}
			button:hover { background: #3a5a9a; }
			button.danger { background: #7a2a2a; }
			button.danger:hover { background: #9a3a3a; }

			.file-grid {
				display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
				gap: 12px;
			}
			.file-card {
				background: #1e1e2e; border: 1px solid #333; border-radius: 8px;
				padding: 14px; transition: border-color 0.2s;
			}
			.file-card:hover { border-color: #64b5f6; }
			.file-icon { font-size: 28px; margin-bottom: 8px; }
			.file-name {
				font-size: 14px; font-weight: 500; margin-bottom: 4px;
				overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
			}
			.file-meta { font-size: 12px; color: #888; margin-bottom: 8px; }
			.file-actions { display: flex; gap: 6px; flex-wrap: wrap; }
			.file-actions button { padding: 6px 12px; font-size: 11px; min-height: 36px; }

			.card-grid {
				display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
				gap: 12px;
			}
			.memory-card {
				background: #1e1e2e; border: 1px solid #333; border-radius: 8px;
				padding: 14px;
			}
			.memory-card:hover { border-color: #81c784; }
			.card-header { display: flex; justify-content: space-between; align-items: start; margin-bottom: 8px; }
			.card-title { font-size: 14px; font-weight: 500; }
			.card-type { font-size: 11px; background: #2a2a3e; padding: 2px 6px; border-radius: 3px; color: #aaa; }
			.card-body { font-size: 13px; color: #aaa; white-space: pre-wrap; word-break: break-word; }

			.empty { text-align: center; color: #666; padding: 40px 20px; font-size: 14px; }
			.loading { text-align: center; color: #888; padding: 40px; }
			.card-form { margin-bottom: 20px; display: flex; flex-direction: column; gap: 8px; }
			.card-form-row { display: flex; gap: 8px; }

			@media (max-width: 768px) {
				.file-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
				.card-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
			}
			@media (max-width: 480px) {
				.file-grid { grid-template-columns: 1fr; }
				.card-grid { grid-template-columns: 1fr; }
				.tabs { gap: 2px; }
				.tab-btn { padding: 6px 12px; font-size: 13px; }
				.upload-section { padding: 12px; }
				.upload-row { flex-direction: column; align-items: stretch; }
				.file-card { padding: 10px; }
				.card-form-row { flex-direction: column; }
				input[type="text"], select, textarea { font-size: 16px; }
			}
		</style>

		<div class="tabs">
			<div class="tab-btn" data-tab="files">📁 Files</div>
			<div class="tab-btn" data-tab="cards">🎴 Memory Cards</div>
			<button class="tab-btn" id="btn-tour" style="margin-left:auto;font-size:0.78rem;padding:4px 10px;opacity:0.7">Tour</button>
		</div>

		${filesActive ? this.renderFilesTab() : this.renderCardsTab()}
		`;

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

		this.shadow.querySelectorAll(".tab-btn").forEach((btn) => {
			btn.addEventListener("click", () => {
				this.tab = (btn as HTMLElement).dataset.tab as "files" | "cards";
				this.render();
			});
		});

		const uploadForm = this.shadow.querySelector("#upload-form");
		if (uploadForm) uploadForm.addEventListener("submit", (e) => this.handleUpload(e));

		const cardForm = this.shadow.querySelector("#card-form");
		if (cardForm) cardForm.addEventListener("submit", (e) => this.handleCreateCard(e));

		this.shadow.querySelectorAll("[data-action]").forEach((btn) => {
			const action = (btn as HTMLElement).dataset.action!;
			const id = (btn as HTMLElement).dataset.id!;
			btn.addEventListener("click", () => {
				if (action === "delete") this.handleDelete(id);
				else if (action === "share") this.handleShare(id);
				else if (action === "delete-card") this.handleDeleteCard(id);
				else if (action === "download") {
					if (this.space === "demo") {
						alert("Download is disabled in demo mode.");
						return;
					}
					const base = this.getApiBase();
					window.open(`${base}/api/files/${id}/download`, "_blank");
				}
			});
		});

		// Make file cards draggable for calendar reminders
		makeDraggableAll(this.shadow, ".file-card[data-collab-id]", (el) => {
			const title = el.querySelector(".file-name")?.textContent || "";
			const id = el.dataset.collabId?.replace("file:", "") || "";
			return title ? { title, module: "rfiles", entityId: id, label: "File", color: "#10b981" } : null;
		});
		makeDraggableAll(this.shadow, ".memory-card[data-collab-id]", (el) => {
			const title = el.querySelector(".card-title")?.textContent || "";
			const id = el.dataset.collabId?.replace("card:", "") || "";
			return title ? { title, module: "rfiles", entityId: id, label: "Card", color: "#10b981" } : null;
		});

		this._tour.renderOverlay();
	}

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

	private renderFilesTab(): string {
		return `
		<div class="upload-section">
			<h3>Upload File</h3>
			<form id="upload-form">
				<div class="upload-row">
					<input type="file" name="file" required>
					<input type="text" name="title" placeholder="Title (optional)" style="flex:1;min-width:120px">
					<button type="submit">Upload</button>
				</div>
			</form>
		</div>

		${this.loading ? '<div class="loading">Loading files...</div>' : ""}
		${!this.loading && this.files.length === 0 ? '<div class="empty">No files yet. Upload one above.</div>' : ""}
		${
			!this.loading && this.files.length > 0
				? `<div class="file-grid">
				${this.files
					.map(
						(f) => `
					<div class="file-card" data-collab-id="file:${f.id}">
						<div class="file-icon">${this.mimeIcon(f.mime_type)}</div>
						<div class="file-name" title="${this.esc(f.original_filename)}">${this.esc(f.title || f.original_filename)}</div>
						<div class="file-meta">${this.formatSize(f.file_size)} &middot; ${this.formatDate(f.created_at)}</div>
						<div class="file-actions">
							<button data-action="download" data-id="${f.id}">Download</button>
							<button data-action="share" data-id="${f.id}">Share</button>
							<button class="danger" data-action="delete" data-id="${f.id}">Delete</button>
						</div>
					</div>
				`,
					)
					.join("")}
			</div>`
				: ""
		}
		`;
	}

	private renderCardsTab(): string {
		return `
		<div class="upload-section">
			<h3>New Memory Card</h3>
			<form id="card-form" class="card-form">
				<div class="card-form-row">
					<input type="text" name="card-title" placeholder="Title" required style="flex:1">
					<select name="card-type">
						<option value="note">Note</option>
						<option value="idea">Idea</option>
						<option value="task">Task</option>
						<option value="reference">Reference</option>
						<option value="quote">Quote</option>
					</select>
					<button type="submit">Add</button>
				</div>
				<textarea name="card-body" placeholder="Body (optional)"></textarea>
			</form>
		</div>

		${this.cards.length === 0 ? '<div class="empty">No memory cards yet.</div>' : ""}
		${
			this.cards.length > 0
				? `<div class="card-grid">
				${this.cards
					.map(
						(c) => `
					<div class="memory-card" data-collab-id="card:${c.id}">
						<div class="card-header">
							<span class="card-title">${this.cardTypeIcon(c.card_type)} ${this.esc(c.title)}</span>
							<span class="card-type">${c.card_type}</span>
						</div>
						${c.body ? `<div class="card-body">${this.esc(c.body)}</div>` : ""}
						<div class="file-actions" style="margin-top:8px">
							<button class="danger" data-action="delete-card" data-id="${c.id}">Delete</button>
						</div>
					</div>
				`,
					)
					.join("")}
			</div>`
				: ""
		}
		`;
	}

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

customElements.define("folk-file-browser", FolkFileBrowser);
