// boolean is Schritt 7 of the module-system migration (see plan): the
// first module with a REAL frontend component, not just a smoke test like
// echo-dummy's. Renders exactly the same checkbox DataGrid.svelte used to
// render inline (same Tailwind classes, same isChecked coercion logic --
// duplicated here on purpose, see modules/formula/src/main.go's
// builtinFunctions comment for why: this side of the module boundary can't
// import the frontend's TS helpers any more than the backend's WASM guests
// can import Go closures).
//
// Deliberately light-DOM (no attachShadow): Tailwind utility classes on the
// host page apply directly to this element's children with no CSS-custom-
// property piercing needed. That's a real simplification, not just a
// shortcut -- a shadow-DOM version would need the host to expose its whole
// Tailwind build as custom properties for this element to consume, for a
// component this simple. Revisit if a future module's styling needs true
// encapsulation.
//
// Contract: a "value" attribute holding JSON (so null/number/string/bool
// all round-trip unambiguously through an HTML attribute, which is always
// just a string), an "editable" attribute ("true"/"false"), and a "commit"
// CustomEvent (detail.value) dispatched whenever the user changes it --
// DataGrid.svelte listens via oncommit={} the same way it'd listen to any
// other DOM event.
function isChecked(value) {
	if (value === true || value === 1) return true;
	if (typeof value === 'string') {
		const normalized = value.trim().toLowerCase();
		return normalized === '1' || normalized === 'true';
	}
	return false;
}

customElements.define(
	'boolean-cell',
	class extends HTMLElement {
		static get observedAttributes() {
			return ['value', 'editable', 'aria-label'];
		}

		connectedCallback() {
			this.render();
		}

		attributeChangedCallback() {
			this.render();
		}

		render() {
			if (!this._input) {
				this._input = document.createElement('input');
				this._input.type = 'checkbox';
				this._input.className =
					'size-4 accent-brand-600 align-middle disabled:cursor-not-allowed disabled:opacity-50';
				this._input.addEventListener('change', () => {
					this.dispatchEvent(
						new CustomEvent('commit', { detail: { value: this._input.checked }, bubbles: true })
					);
				});
				this.appendChild(this._input);
			}

			let raw = null;
			try {
				raw = JSON.parse(this.getAttribute('value') ?? 'null');
			} catch {
				raw = null;
			}
			this._input.checked = isChecked(raw);
			this._input.disabled = this.getAttribute('editable') !== 'true';
			const label = this.getAttribute('aria-label');
			if (label) this._input.setAttribute('aria-label', label);
		}
	}
);
