/**
 * folk-holon-browser — Canvas shape for searching and browsing holons.
 *
 * Ported from canvas-website HolonBrowser.tsx (React) to FolkShape
 * web component. Searches H3 cell IDs or coordinates, probes standard
 * lenses, and dispatches "open-holon" CustomEvent for canvas to create
 * a folk-holon shape.
 */

import * as h3 from 'h3-js';
import { FolkShape } from './folk-shape';
import { css, html } from './tags';
import {
	isValidHolonId,
	isH3CellId,
	getResolutionName,
	getResolutionDescription,
	STANDARD_LENSES,
	LENS_ICONS,
	getAvailableLenses,
	getLensData,
	type HolonData,
} from './holon-service';

const styles = css`
	:host {
		background: var(--rs-bg-surface, #fff);
		color: var(--rs-text-primary, #1e293b);
		border-radius: 8px;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
		min-width: 360px;
		min-height: 300px;
	}

	.header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		background: #22c55e;
		color: white;
		border-radius: 8px 8px 0 0;
		font-size: 12px;
		font-weight: 600;
		cursor: move;
	}

	.header-title {
		display: flex;
		align-items: center;
		gap: 6px;
	}

	.header-actions button {
		background: transparent;
		border: none;
		color: white;
		cursor: pointer;
		padding: 2px 6px;
		border-radius: 4px;
		font-size: 14px;
	}

	.header-actions button:hover {
		background: rgba(255, 255, 255, 0.2);
	}

	.content {
		padding: 16px;
		overflow: auto;
		height: calc(100% - 36px);
		display: flex;
		flex-direction: column;
		gap: 16px;
	}

	.search-row {
		display: flex;
		gap: 8px;
	}

	.search-input {
		flex: 1;
		padding: 8px 12px;
		border: 1px solid var(--rs-border, rgba(255, 255, 255, 0.1));
		border-radius: 6px;
		font-size: 13px;
		font-family: monospace;
		outline: none;
	}

	.search-input:focus {
		border-color: #22c55e;
		box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2);
	}

	.search-btn {
		padding: 8px 16px;
		background: #3b82f6;
		color: white;
		border: none;
		border-radius: 6px;
		cursor: pointer;
		font-size: 13px;
		font-weight: 600;
	}

	.search-btn:hover { background: #2563eb; }
	.search-btn:disabled { background: #9ca3af; cursor: not-allowed; }

	.error {
		color: #dc2626;
		font-size: 12px;
	}

	.result-card {
		border: 1px solid var(--rs-border, rgba(255, 255, 255, 0.1));
		border-radius: 8px;
		padding: 14px;
	}

	.result-name {
		font-size: 15px;
		font-weight: 600;
		color: var(--rs-text-primary, #e2e8f0);
		margin-bottom: 8px;
	}

	.result-grid {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: 6px;
		margin-bottom: 12px;
		font-size: 12px;
	}

	.result-label {
		color: var(--rs-text-muted, #64748b);
		font-size: 11px;
	}

	.result-value {
		color: var(--rs-text-primary, #e2e8f0);
		font-family: monospace;
		font-size: 12px;
		word-break: break-all;
	}

	.lens-badges {
		display: flex;
		flex-wrap: wrap;
		gap: 4px;
		margin-bottom: 12px;
	}

	.lens-badge {
		padding: 3px 8px;
		border-radius: 10px;
		font-size: 11px;
		background: rgba(59, 130, 246, 0.15);
		color: #60a5fa;
	}

	.lens-badge.empty {
		background: var(--rs-bg-surface-raised, #334155);
		color: var(--rs-text-muted, #64748b);
	}

	.action-row {
		display: flex;
		gap: 8px;
		padding-top: 12px;
		border-top: 1px solid var(--rs-border, rgba(255, 255, 255, 0.1));
	}

	.open-btn {
		padding: 8px 16px;
		background: #22c55e;
		color: white;
		border: none;
		border-radius: 6px;
		cursor: pointer;
		font-size: 13px;
		font-weight: 600;
	}

	.open-btn:hover { background: #16a34a; }

	.reset-btn {
		padding: 8px 16px;
		background: var(--rs-bg-surface-raised, #334155);
		color: var(--rs-text-primary, #e2e8f0);
		border: none;
		border-radius: 6px;
		cursor: pointer;
		font-size: 13px;
	}

	.reset-btn:hover { background: var(--rs-bg-hover, rgba(255, 255, 255, 0.05)); }

	.loading {
		color: var(--rs-text-muted, #64748b);
		font-size: 13px;
		padding: 8px 0;
	}

	.hint {
		font-size: 12px;
		color: var(--rs-text-muted, #64748b);
	}
`;

declare global {
	interface HTMLElementTagNameMap {
		'folk-holon-browser': FolkHolonBrowser;
	}
}

export class FolkHolonBrowser extends FolkShape {
	static override tagName = 'folk-holon-browser';

	static {
		const sheet = new CSSStyleSheet();
		const parentRules = Array.from(FolkShape.styles.cssRules).map((r) => r.cssText).join('\n');
		const childRules = Array.from(styles.cssRules).map((r) => r.cssText).join('\n');
		sheet.replaceSync(`${parentRules}\n${childRules}`);
		this.styles = sheet;
	}

	// ── State ──
	#searchId = '';
	#result: HolonData | null = null;
	#availableLenses: string[] = [];
	#loading = false;
	#error = '';
	#contentEl: HTMLElement | null = null;

	override createRenderRoot() {
		const root = super.createRenderRoot();

		const wrapper = document.createElement('div');
		wrapper.style.cssText = 'width:100%;height:100%;display:flex;flex-direction:column;';
		wrapper.innerHTML = html`
			<div class="header">
				<span class="header-title">
					<span>🔍</span>
					<span>Holon Browser</span>
				</span>
				<div class="header-actions">
					<button class="close-btn" title="Close">×</button>
				</div>
			</div>
			<div class="content"></div>
		`;

		const slot = root.querySelector('slot');
		const containerDiv = slot?.parentElement as HTMLElement;
		if (containerDiv) containerDiv.replaceWith(wrapper);

		this.#contentEl = wrapper.querySelector('.content');

		wrapper.querySelector('.close-btn')!.addEventListener('click', (e) => {
			e.stopPropagation();
			this.dispatchEvent(new CustomEvent('close'));
		});

		this.#render();
		return root;
	}

	// ── Search ──

	async #handleSearch() {
		const id = this.#searchId.trim();
		if (!id) { this.#error = 'Please enter a Holon ID'; this.#render(); return; }
		if (!isValidHolonId(id)) {
			this.#error = 'Invalid ID. Enter an H3 cell (e.g. 872a1070bffffff) or numeric ID.';
			this.#render();
			return;
		}

		this.#error = '';
		this.#loading = true;
		this.#render();

		try {
			let lat = 0, lng = 0, resolution = -1, name = `Holon ${id.slice(-8)}`;

			if (isH3CellId(id)) {
				[lat, lng] = h3.cellToLatLng(id);
				resolution = h3.getResolution(id);
				name = `${getResolutionName(resolution)} Holon`;
			}

			this.#result = {
				id,
				name,
				description: resolution >= 0 ? getResolutionDescription(resolution) : '',
				latitude: lat,
				longitude: lng,
				resolution,
				timestamp: Date.now(),
			};

			// Probe lenses
			this.#availableLenses = await getAvailableLenses(id);
			if (this.#availableLenses.length === 0) {
				this.#availableLenses = ['general'];
			}
		} catch (e) {
			this.#error = `Search failed: ${e instanceof Error ? e.message : 'Unknown error'}`;
			this.#result = null;
		} finally {
			this.#loading = false;
			this.#render();
		}
	}

	#handleOpenHolon() {
		if (!this.#result) return;
		this.dispatchEvent(new CustomEvent('open-holon', {
			bubbles: true,
			detail: { holon: this.#result, lenses: this.#availableLenses },
		}));
	}

	#handleReset() {
		this.#searchId = '';
		this.#result = null;
		this.#availableLenses = [];
		this.#error = '';
		this.#render();
	}

	// ── Rendering ──

	#render() {
		if (!this.#contentEl) return;

		const result = this.#result;
		const isGeo = result && result.resolution >= 0;

		let resultHtml = '';
		if (result) {
			const infoGrid = isGeo
				? html`
					<div class="result-grid">
						<div>
							<div class="result-label">Coordinates</div>
							<div class="result-value">${result.latitude.toFixed(6)}, ${result.longitude.toFixed(6)}</div>
						</div>
						<div>
							<div class="result-label">Resolution</div>
							<div class="result-value">${getResolutionName(result.resolution)} (Level ${result.resolution})</div>
						</div>
						<div>
							<div class="result-label">Holon ID</div>
							<div class="result-value">${result.id}</div>
						</div>
						<div>
							<div class="result-label">Description</div>
							<div class="result-value">${getResolutionDescription(result.resolution)}</div>
						</div>
					</div>`
				: html`
					<div class="result-grid">
						<div>
							<div class="result-label">Type</div>
							<div class="result-value" style="color:#22c55e;font-weight:600">Workspace / Group</div>
						</div>
						<div>
							<div class="result-label">Holon ID</div>
							<div class="result-value">${result.id}</div>
						</div>
					</div>`;

			const lensBadges = this.#availableLenses.map((lens) => {
				const icon = LENS_ICONS[lens] ?? '📁';
				return `<span class="lens-badge">${icon} ${lens}</span>`;
			}).join('');

			resultHtml = html`
				<div class="result-card">
					<div class="result-name">📍 ${escapeHtml(result.name)}</div>
					${infoGrid}
					<div class="result-label" style="margin-bottom:4px">Available Data</div>
					<div class="lens-badges">${lensBadges || '<span class="lens-badge empty">No data yet</span>'}</div>
					<div class="action-row">
						<button class="open-btn">Open Holon</button>
						<button class="reset-btn">Search Another</button>
					</div>
				</div>`;
		}

		this.#contentEl.innerHTML = html`
			<div class="hint">Search by H3 cell ID (e.g. <code>872a1070bffffff</code>) or numeric Holon ID</div>
			<div class="search-row">
				<input class="search-input" type="text" placeholder="Holon ID..." value="${escapeHtml(this.#searchId)}" />
				<button class="search-btn" ${this.#loading ? 'disabled' : ''}>${this.#loading ? 'Searching...' : 'Search'}</button>
			</div>
			${this.#error ? `<div class="error">${escapeHtml(this.#error)}</div>` : ''}
			${resultHtml}
		`;

		// Wire events
		const input = this.#contentEl.querySelector('.search-input') as HTMLInputElement;
		const searchBtn = this.#contentEl.querySelector('.search-btn') as HTMLButtonElement;

		input?.addEventListener('input', (e) => { this.#searchId = (e.target as HTMLInputElement).value; });
		input?.addEventListener('pointerdown', (e) => e.stopPropagation());
		input?.addEventListener('keydown', (e) => {
			e.stopPropagation();
			if (e.key === 'Enter') this.#handleSearch();
		});
		searchBtn?.addEventListener('click', (e) => { e.stopPropagation(); this.#handleSearch(); });

		const openBtn = this.#contentEl.querySelector('.open-btn');
		const resetBtn = this.#contentEl.querySelector('.reset-btn');
		openBtn?.addEventListener('click', (e) => { e.stopPropagation(); this.#handleOpenHolon(); });
		resetBtn?.addEventListener('click', (e) => { e.stopPropagation(); this.#handleReset(); });
	}

	// ── Serialization ──

	override toJSON() {
		return { ...super.toJSON(), type: 'folk-holon-browser' };
	}

	static override fromData(data: Record<string, any>): FolkHolonBrowser {
		return FolkShape.fromData(data) as FolkHolonBrowser;
	}
}

function escapeHtml(str: string): string {
	return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
