/**
 * <rstack-module-setup> — Inline module configuration card.
 *
 * Renders a module's settingsSchema form directly in context (e.g. inside
 * an unconfigured newsletter manager) so admins can configure without
 * navigating to space settings.
 *
 * Attributes: space, module-id, role
 * Dispatches: module-configured (bubbles, composed) on successful save.
 */

const SESSION_KEY = "encryptid_session";

interface SettingField {
	key: string;
	label: string;
	type: string;
	description?: string;
	default?: string | boolean;
	options?: Array<{ value: string; label: string }>;
}

interface ModConfig {
	id: string;
	name: string;
	icon: string;
	settingsSchema?: SettingField[];
	settings?: Record<string, string | boolean>;
}

function getToken(): string | null {
	try {
		const raw = localStorage.getItem(SESSION_KEY);
		if (!raw) return null;
		return JSON.parse(raw)?.accessToken || null;
	} catch { return null; }
}

export class RStackModuleSetup extends HTMLElement {
	private _space = "";
	private _moduleId = "";
	private _role = "viewer";
	private _schema: SettingField[] = [];
	private _values: Record<string, string | boolean> = {};
	private _moduleName = "";
	private _moduleIcon = "";
	private _loading = true;
	private _saving = false;
	private _error = "";
	private _success = false;

	static define() {
		if (!customElements.get("rstack-module-setup")) {
			customElements.define("rstack-module-setup", RStackModuleSetup);
		}
	}

	static get observedAttributes() { return ["space", "module-id", "role"]; }

	attributeChangedCallback(name: string, _old: string, val: string) {
		if (name === "space") this._space = val;
		else if (name === "module-id") this._moduleId = val;
		else if (name === "role") this._role = val;
	}

	connectedCallback() {
		this._space = this.getAttribute("space") || "";
		this._moduleId = this.getAttribute("module-id") || "";
		this._role = this.getAttribute("role") || "viewer";
		if (!this.shadowRoot) this.attachShadow({ mode: "open" });
		this._loadSchema();
	}

	private get _isAdmin(): boolean {
		return this._role === "admin";
	}

	private async _loadSchema() {
		this._loading = true;
		this._render();

		if (!this._space || !this._moduleId) {
			this._loading = false;
			this._render();
			return;
		}

		const token = getToken();
		try {
			const res = await fetch(`/api/spaces/${encodeURIComponent(this._space)}/modules`, {
				headers: token ? { Authorization: `Bearer ${token}` } : {},
			});
			if (!res.ok) throw new Error("Failed to load modules");
			const data = await res.json();
			const mod: ModConfig | undefined = (data.modules || []).find((m: ModConfig) => m.id === this._moduleId);
			if (mod?.settingsSchema) {
				this._schema = mod.settingsSchema;
				this._moduleName = mod.name;
				this._moduleIcon = mod.icon;
				// Populate current values
				this._values = {};
				for (const field of this._schema) {
					this._values[field.key] = mod.settings?.[field.key] ?? field.default ?? "";
				}
			}
		} catch (e: any) {
			this._error = e.message || "Failed to load settings";
		}

		this._loading = false;
		this._render();
	}

	private _render() {
		if (!this.shadowRoot) return;

		if (this._loading) {
			this.shadowRoot.innerHTML = `<style>${SETUP_CSS}</style><div class="setup-card"><div class="loading">Loading configuration...</div></div>`;
			return;
		}

		if (this._success) {
			this.shadowRoot.innerHTML = `<style>${SETUP_CSS}</style><div class="setup-card success"><div class="success-icon">&#10003;</div><div class="success-text">Configuration saved!</div></div>`;
			return;
		}

		if (this._schema.length === 0) {
			this.shadowRoot.innerHTML = `<style>${SETUP_CSS}</style><div class="setup-card"><div class="empty">No settings available for this module.</div></div>`;
			return;
		}

		if (!this._isAdmin) {
			this.shadowRoot.innerHTML = `<style>${SETUP_CSS}</style>
				<div class="setup-card">
					<div class="setup-header">
						<span class="setup-icon">${this._moduleIcon}</span>
						<span class="setup-title">${this._esc(this._moduleName)} Configuration Required</span>
					</div>
					<p class="setup-desc">A space admin needs to configure ${this._esc(this._moduleName)} before it can be used.</p>
				</div>`;
			return;
		}

		const fieldsHTML = this._schema.map(field => {
			const val = this._values[field.key] ?? "";
			let inputHTML = "";

			if (field.type === "boolean") {
				inputHTML = `<label class="toggle"><input type="checkbox" class="setup-field" data-key="${field.key}" ${val ? "checked" : ""} /><span class="toggle-label">Enabled</span></label>`;
			} else if (field.type === "select") {
				inputHTML = `<select class="setup-field input" data-key="${field.key}">${(field.options || []).map(o => `<option value="${o.value}" ${val === o.value ? "selected" : ""}>${o.label}</option>`).join("")}</select>`;
			} else if (field.type === "password") {
				inputHTML = `<input type="password" class="setup-field input" data-key="${field.key}" value="${typeof val === "string" ? this._escAttr(val) : ""}" autocomplete="off" />`;
			} else {
				inputHTML = `<input type="text" class="setup-field input" data-key="${field.key}" value="${typeof val === "string" ? this._escAttr(val) : ""}" />`;
			}

			return `
				<div class="field-group">
					<label class="field-label">${this._esc(field.label)}</label>
					${inputHTML}
					${field.description ? `<div class="field-desc">${this._esc(field.description)}</div>` : ""}
				</div>
			`;
		}).join("");

		this.shadowRoot.innerHTML = `
			<style>${SETUP_CSS}</style>
			<div class="setup-card">
				<div class="setup-header">
					<span class="setup-icon">${this._moduleIcon}</span>
					<span class="setup-title">Configure ${this._esc(this._moduleName)}</span>
				</div>
				<div class="setup-fields">${fieldsHTML}</div>
				${this._error ? `<div class="error-msg">${this._esc(this._error)}</div>` : ""}
				<button class="save-btn" id="save-btn" ${this._saving ? "disabled" : ""}>
					${this._saving ? "Saving..." : "Save & Continue"}
				</button>
			</div>
		`;

		this._bindEvents();
	}

	private _bindEvents() {
		const sr = this.shadowRoot!;

		sr.getElementById("save-btn")?.addEventListener("click", () => this._save());

		// Track field changes
		sr.querySelectorAll(".setup-field").forEach(el => {
			el.addEventListener("change", () => {
				const input = el as HTMLInputElement | HTMLSelectElement;
				const key = input.dataset.key!;
				if (input.type === "checkbox") {
					this._values[key] = (input as HTMLInputElement).checked;
				} else {
					this._values[key] = input.value;
				}
			});
			el.addEventListener("input", () => {
				const input = el as HTMLInputElement;
				const key = input.dataset.key!;
				if (input.type !== "checkbox") {
					this._values[key] = input.value;
				}
			});
		});
	}

	private async _save() {
		this._saving = true;
		this._error = "";
		this._render();

		const token = getToken();
		if (!token) {
			this._error = "Not authenticated";
			this._saving = false;
			this._render();
			return;
		}

		try {
			const res = await fetch(`/api/spaces/${encodeURIComponent(this._space)}/modules`, {
				method: "PATCH",
				headers: {
					"Content-Type": "application/json",
					Authorization: `Bearer ${token}`,
				},
				body: JSON.stringify({
					moduleSettings: { [this._moduleId]: this._values },
				}),
			});

			if (!res.ok) {
				const err = await res.json().catch(() => ({}));
				throw new Error(err.error || `Save failed (${res.status})`);
			}

			this._success = true;
			this._render();

			// Dispatch event so parent components can react
			this.dispatchEvent(new CustomEvent("module-configured", {
				bubbles: true,
				composed: true,
				detail: { moduleId: this._moduleId, space: this._space },
			}));
		} catch (e: any) {
			this._error = e.message || "Failed to save";
			this._saving = false;
			this._render();
		}
	}

	private _esc(s: string): string {
		return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
	}

	private _escAttr(s: string): string {
		return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
	}
}

const SETUP_CSS = `
:host {
	display: block;
}

.setup-card {
	max-width: 480px;
	margin: 2rem auto;
	padding: 24px;
	background: var(--rs-bg-surface, #1e1e2e);
	border: 1px solid var(--rs-border, #333);
	border-radius: 12px;
}

.setup-card.success {
	text-align: center;
	padding: 32px 24px;
}

.success-icon {
	font-size: 2.5rem;
	color: #14b8a6;
	margin-bottom: 8px;
}

.success-text {
	font-size: 1rem;
	color: var(--rs-text-primary, #e5e5e5);
	font-weight: 500;
}

.setup-header {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 20px;
}

.setup-icon {
	font-size: 1.5rem;
}

.setup-title {
	font-size: 1.05rem;
	font-weight: 600;
	color: var(--rs-text-primary, #e5e5e5);
}

.setup-desc {
	font-size: 0.85rem;
	color: var(--rs-text-secondary, #aaa);
	margin: 0;
	line-height: 1.5;
}

.setup-fields {
	display: flex;
	flex-direction: column;
	gap: 14px;
	margin-bottom: 16px;
}

.field-group {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.field-label {
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--rs-text-secondary, #a3a3a3);
}

.input {
	background: var(--rs-border-subtle, #0a0a0a);
	border: 1px solid var(--rs-border, #404040);
	color: var(--rs-text-primary, #e5e5e5);
	border-radius: 8px;
	padding: 8px 12px;
	font-size: 0.85rem;
	width: 100%;
	box-sizing: border-box;
}
.input:focus {
	outline: none;
	border-color: #14b8a6;
}

.toggle {
	display: flex;
	align-items: center;
	gap: 8px;
	cursor: pointer;
}

.toggle-label {
	font-size: 0.82rem;
	color: var(--rs-text-secondary, #aaa);
}

.field-desc {
	font-size: 0.7rem;
	color: var(--rs-text-muted, #525252);
	line-height: 1.4;
}

.error-msg {
	font-size: 0.78rem;
	color: #f87171;
	margin-bottom: 12px;
}

.save-btn {
	width: 100%;
	padding: 10px 16px;
	background: linear-gradient(135deg, #14b8a6, #0d9488);
	border: none;
	color: white;
	border-radius: 8px;
	font-size: 0.88rem;
	font-weight: 600;
	cursor: pointer;
	transition: opacity 0.15s;
}
.save-btn:hover { opacity: 0.9; }
.save-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.loading, .empty {
	text-align: center;
	padding: 16px 0;
	font-size: 0.85rem;
	color: var(--rs-text-muted, #737373);
}
`;
