/**
 * <rstack-user-dashboard> — Shown when all tabs are closed.
 *
 * Displays a spaces grid (sorted by most recent visit), notifications panel,
 * and quick-action buttons. Dispatches `dashboard-navigate` events to open
 * rApps in new tabs.
 *
 * Attributes:
 *   space — current space slug (for context)
 */

import { getSession, getAccessToken } from "./rstack-identity";

interface SpaceInfo {
	slug: string;
	name: string;
	icon?: string;
	role?: string;
	visibility?: string;
	relationship?: string;
	createdAt?: string;
}

interface NotificationItem {
	id: string;
	category: string;
	title: string;
	body: string | null;
	actionUrl: string | null;
	createdAt: string;
	read: boolean;
}

const RECENT_KEY = "rspace_recent_spaces";

export class RStackUserDashboard extends HTMLElement {
	#shadow: ShadowRoot;
	#spaces: SpaceInfo[] = [];
	#notifications: NotificationItem[] = [];
	#loading = true;
	#notifLoading = true;

	constructor() {
		super();
		this.#shadow = this.attachShadow({ mode: "open" });
	}

	static get observedAttributes() {
		return ["space"];
	}

	get space(): string {
		return this.getAttribute("space") || "";
	}

	connectedCallback() {
		this.#render();
		this.#loadData();
	}

	attributeChangedCallback() {
		this.#render();
	}

	/** Reload data when dashboard becomes visible again */
	refresh() {
		this.#loading = true;
		this.#notifLoading = true;
		this.#render();
		this.#loadData();
	}

	async #loadData() {
		await Promise.all([this.#fetchSpaces(), this.#fetchNotifications()]);
	}

	async #fetchSpaces() {
		this.#loading = true;
		try {
			const headers: Record<string, string> = {};
			const token = getAccessToken();
			if (token) headers["Authorization"] = `Bearer ${token}`;

			const res = await fetch("/api/spaces", { headers });
			if (res.ok) {
				const data = await res.json();
				this.#spaces = data.spaces || [];
			}
		} catch {
			// Offline or API unavailable
		}
		this.#loading = false;
		this.#render();
	}

	async #fetchNotifications() {
		this.#notifLoading = true;
		const token = getAccessToken();
		if (!token) {
			this.#notifLoading = false;
			this.#render();
			return;
		}

		try {
			const res = await fetch("/api/notifications?limit=10", {
				headers: { Authorization: `Bearer ${token}` },
			});
			if (res.ok) {
				const data = await res.json();
				this.#notifications = data.notifications || [];
			}
		} catch {
			// Silently fail
		}
		this.#notifLoading = false;
		this.#render();
	}

	async #markAllRead() {
		const token = getAccessToken();
		if (!token) return;

		try {
			await fetch("/api/notifications/read-all", {
				method: "POST",
				headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
				body: "{}",
			});
		} catch { /* best-effort */ }

		this.#notifications.forEach(n => n.read = true);
		this.#render();
	}

	#getRecentVisits(): Record<string, number> {
		try {
			const raw = localStorage.getItem(RECENT_KEY);
			return raw ? JSON.parse(raw) : {};
		} catch {
			return {};
		}
	}

	#getSortedSpaces(): SpaceInfo[] {
		const visits = this.#getRecentVisits();
		return [...this.#spaces].sort((a, b) => {
			const va = visits[a.slug] || 0;
			const vb = visits[b.slug] || 0;
			if (va !== vb) return vb - va; // most recent first
			// Fall back to createdAt
			const ca = a.createdAt ? new Date(a.createdAt).getTime() : 0;
			const cb = b.createdAt ? new Date(b.createdAt).getTime() : 0;
			return cb - ca;
		});
	}

	#timeAgo(iso: string): string {
		const diff = Date.now() - new Date(iso).getTime();
		const mins = Math.floor(diff / 60_000);
		if (mins < 1) return "just now";
		if (mins < 60) return `${mins}m ago`;
		const hrs = Math.floor(mins / 60);
		if (hrs < 24) return `${hrs}h ago`;
		const days = Math.floor(hrs / 24);
		if (days < 30) return `${days}d ago`;
		return `${Math.floor(days / 30)}mo ago`;
	}

	#spaceInitial(space: SpaceInfo): string {
		if (space.icon) return space.icon;
		return (space.name || space.slug).charAt(0).toUpperCase();
	}

	#roleBadge(role?: string): string {
		if (!role || role === "owner") return "";
		if (role === "admin") return `<span class="role-badge role-admin">admin</span>`;
		if (role === "member") return `<span class="role-badge role-member">member</span>`;
		if (role === "viewer") return `<span class="role-badge role-viewer">view</span>`;
		return `<span class="role-badge">${role}</span>`;
	}

	#dispatch(moduleId: string, spaceSlug?: string) {
		this.dispatchEvent(new CustomEvent("dashboard-navigate", {
			bubbles: true,
			detail: { moduleId, spaceSlug: spaceSlug || this.space },
		}));
	}

	#parseActionUrl(url: string | null): { moduleId: string; spaceSlug?: string } | null {
		if (!url) return null;
		try {
			// Handle relative URLs like /myspace/rnotes or /rnotes
			const parts = url.replace(/^\//, "").split("/");
			if (parts.length >= 2) return { spaceSlug: parts[0], moduleId: parts[1] };
			if (parts.length === 1 && parts[0]) return { moduleId: parts[0] };
		} catch { /* fall through */ }
		return null;
	}

	#render() {
		const session = getSession();
		const spaces = this.#getSortedSpaces();
		const visits = this.#getRecentVisits();
		const unreadCount = this.#notifications.filter(n => !n.read).length;

		// ── Spaces grid ──
		let spacesHTML: string;
		if (this.#loading) {
			spacesHTML = `<div class="section-empty">Loading spaces...</div>`;
		} else if (spaces.length === 0) {
			spacesHTML = `<div class="section-empty">No spaces found</div>`;
		} else {
			spacesHTML = spaces.map(s => {
				const lastVisit = visits[s.slug];
				const timeLabel = lastVisit ? this.#timeAgo(new Date(lastVisit).toISOString()) : "";
				return `
					<button class="space-card" data-space="${s.slug}" data-module="rspace">
						<div class="space-icon">${this.#spaceInitial(s)}</div>
						<div class="space-info">
							<div class="space-name">${s.name || s.slug}</div>
							<div class="space-meta">
								${this.#roleBadge(s.role)}
								${timeLabel ? `<span class="space-time">${timeLabel}</span>` : ""}
							</div>
						</div>
					</button>
				`;
			}).join("");
		}

		// ── Notifications ──
		let notifsHTML: string;
		if (!session) {
			notifsHTML = `<div class="section-empty">Sign in to see notifications</div>`;
		} else if (this.#notifLoading) {
			notifsHTML = `<div class="section-empty">Loading...</div>`;
		} else if (this.#notifications.length === 0) {
			notifsHTML = `<div class="section-empty">No notifications</div>`;
		} else {
			notifsHTML = this.#notifications.map(n => `
				<button class="notif-item ${n.read ? "read" : "unread"}" data-action-url="${n.actionUrl || ""}">
					<div class="notif-content">
						<div class="notif-title">${n.title}</div>
						${n.body ? `<div class="notif-body">${n.body}</div>` : ""}
					</div>
					<span class="notif-time">${this.#timeAgo(n.createdAt)}</span>
				</button>
			`).join("");
		}

		this.#shadow.innerHTML = `
			<style>${STYLES}</style>
			<div class="dashboard">
				<div class="dashboard-inner">
					<div class="section section--spaces">
						<div class="section-header">
							<h2>Your Spaces</h2>
						</div>
						<div class="spaces-grid">${spacesHTML}</div>
					</div>

					<div class="section section--notifications">
						<div class="section-header">
							<h2>Notifications ${unreadCount > 0 ? `<span class="unread-badge">${unreadCount}</span>` : ""}</h2>
							${unreadCount > 0 ? `<button class="mark-all-btn" id="mark-all-read">Mark all read</button>` : ""}
						</div>
						<div class="notifs-list">${notifsHTML}</div>
					</div>

					<div class="section section--actions">
						<div class="section-header"><h2>Quick Actions</h2></div>
						<div class="actions-row">
							<button class="action-btn" data-action-module="rmeets">
								<span class="action-icon">📹</span>
								<span>Quick Meet</span>
							</button>
							<button class="action-btn" data-action-module="rnotes">
								<span class="action-icon">📝</span>
								<span>New Note</span>
							</button>
							<button class="action-btn" data-action-module="rspace">
								<span class="action-icon">🌌</span>
								<span>Canvas</span>
							</button>
						</div>
					</div>
				</div>
			</div>
		`;

		this.#attachEvents();
	}

	#attachEvents() {
		// Space cards
		this.#shadow.querySelectorAll(".space-card").forEach(el => {
			el.addEventListener("click", () => {
				const space = (el as HTMLElement).dataset.space!;
				const mod = (el as HTMLElement).dataset.module || "rspace";
				this.#dispatch(mod, space);
			});
		});

		// Notification items
		this.#shadow.querySelectorAll(".notif-item").forEach(el => {
			el.addEventListener("click", () => {
				const url = (el as HTMLElement).dataset.actionUrl;
				const parsed = this.#parseActionUrl(url || null);
				if (parsed) {
					this.#dispatch(parsed.moduleId, parsed.spaceSlug);
				} else {
					// Default: open canvas in current space
					this.#dispatch("rspace");
				}
			});
		});

		// Mark all read
		this.#shadow.getElementById("mark-all-read")?.addEventListener("click", (e) => {
			e.stopPropagation();
			this.#markAllRead();
		});

		// Quick action buttons
		this.#shadow.querySelectorAll(".action-btn").forEach(el => {
			el.addEventListener("click", () => {
				const mod = (el as HTMLElement).dataset.actionModule!;
				this.#dispatch(mod);
			});
		});
	}

	static define(tag = "rstack-user-dashboard") {
		if (!customElements.get(tag)) customElements.define(tag, RStackUserDashboard);
	}
}

// ============================================================================
// STYLES
// ============================================================================

const STYLES = `
:host {
  display: block;
  width: 100%;
  height: 100%;
}

.dashboard {
  min-height: 100%;
  padding: 32px 24px;
  overflow-y: auto;
  background: var(--rs-bg, #0f172a);
}

.dashboard-inner {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 32px;
}

/* ── Sections ── */

.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.section-header h2 {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--rs-text-primary, #e2e8f0);
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-empty {
  padding: 24px 16px;
  text-align: center;
  color: var(--rs-text-muted, #94a3b8);
  font-size: 0.8rem;
}

.unread-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: #ef4444;
  color: white;
  font-size: 0.7rem;
  font-weight: 700;
}

.mark-all-btn {
  background: none;
  border: none;
  color: var(--rs-accent, #06b6d4);
  font-size: 0.75rem;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  transition: background 0.15s;
}
.mark-all-btn:hover {
  background: var(--rs-bg-hover, rgba(255,255,255,0.05));
}

/* ── Spaces grid ── */

.spaces-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 10px;
}

.space-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: 10px;
  background: var(--rs-bg-surface, #1e293b);
  border: 1px solid var(--rs-border, rgba(255,255,255,0.08));
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
  text-align: left;
  color: inherit;
  font: inherit;
}
.space-card:hover {
  background: var(--rs-bg-hover, rgba(255,255,255,0.06));
  border-color: var(--rs-accent, #06b6d4);
  transform: translateY(-1px);
}

.space-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: linear-gradient(135deg, rgba(6,182,212,0.15), rgba(94,234,212,0.1));
  color: var(--rs-accent, #06b6d4);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  font-weight: 700;
  flex-shrink: 0;
}

.space-info {
  min-width: 0;
  flex: 1;
}

.space-name {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--rs-text-primary, #e2e8f0);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.space-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 3px;
}

.space-time {
  font-size: 0.7rem;
  color: var(--rs-text-muted, #64748b);
}

.role-badge {
  font-size: 0.65rem;
  padding: 1px 5px;
  border-radius: 4px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.role-admin { background: rgba(251,191,36,0.15); color: #fbbf24; }
.role-member { background: rgba(96,165,250,0.15); color: #60a5fa; }
.role-viewer { background: rgba(148,163,184,0.15); color: #94a3b8; }

/* ── Notifications ── */

.notifs-list {
  display: flex;
  flex-direction: column;
  border-radius: 10px;
  background: var(--rs-bg-surface, #1e293b);
  border: 1px solid var(--rs-border, rgba(255,255,255,0.08));
  overflow: hidden;
}

.notif-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 16px;
  cursor: pointer;
  transition: background 0.15s;
  border-bottom: 1px solid var(--rs-border, rgba(255,255,255,0.06));
  background: none;
  border-left: none;
  border-right: none;
  border-top: none;
  text-align: left;
  color: inherit;
  font: inherit;
  width: 100%;
}
.notif-item:last-child { border-bottom: none; }
.notif-item:hover {
  background: var(--rs-bg-hover, rgba(255,255,255,0.05));
}
.notif-item.unread {
  background: rgba(6,182,212,0.04);
}
.notif-item.unread .notif-title {
  font-weight: 600;
}

.notif-content {
  flex: 1;
  min-width: 0;
}

.notif-title {
  font-size: 0.8rem;
  color: var(--rs-text-primary, #e2e8f0);
  line-height: 1.3;
}

.notif-body {
  font-size: 0.75rem;
  color: var(--rs-text-muted, #94a3b8);
  margin-top: 2px;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.notif-time {
  font-size: 0.7rem;
  color: var(--rs-text-muted, #64748b);
  flex-shrink: 0;
  white-space: nowrap;
  margin-top: 2px;
}

/* ── Quick Actions ── */

.actions-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.action-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: 8px;
  background: var(--rs-bg-surface, #1e293b);
  border: 1px solid var(--rs-border, rgba(255,255,255,0.08));
  color: var(--rs-text-primary, #e2e8f0);
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  font: inherit;
}
.action-btn:hover {
  background: var(--rs-bg-hover, rgba(255,255,255,0.06));
  border-color: var(--rs-accent, #06b6d4);
}

.action-icon {
  font-size: 1rem;
}

/* ── Responsive ── */

@media (max-width: 480px) {
  .dashboard {
    padding: 20px 12px;
  }
  .spaces-grid {
    grid-template-columns: 1fr;
  }
}
`;
