/**
 * folk-gov-project — Circuit Aggregator
 *
 * Traverses the arrow graph backward from itself to discover all upstream
 * governance gates. Shows "X of Y gates satisfied" with a progress bar
 * and requirement checklist. Auto-detects completion.
 */

import { FolkShape } from "./folk-shape";
import { css, html } from "./tags";
import type { PortDescriptor } from "./data-types";

const HEADER_COLOR = "#1d4ed8";
const GOV_TAG_NAMES = new Set([
	"FOLK-GOV-BINARY",
	"FOLK-GOV-THRESHOLD",
	"FOLK-GOV-KNOB",
	"FOLK-GOV-AMENDMENT",
	"FOLK-GOV-QUADRATIC",
	"FOLK-GOV-CONVICTION",
	"FOLK-GOV-MULTISIG",
]);

type ProjectStatus = "draft" | "active" | "completed" | "archived";

interface GateInfo {
	id: string;
	tagName: string;
	title: string;
	satisfied: boolean;
}

const styles = css`
	:host {
		background: var(--rs-bg-surface, #1e293b);
		border-radius: 10px;
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.25);
		min-width: 280px;
		min-height: 180px;
		overflow: hidden;
	}

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

	.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);
	}

	.body {
		display: flex;
		flex-direction: column;
		padding: 12px;
		gap: 8px;
		overflow-y: auto;
		max-height: calc(100% - 36px);
	}

	.title-input {
		background: transparent;
		border: none;
		color: var(--rs-text-primary, #e2e8f0);
		font-size: 14px;
		font-weight: 700;
		width: 100%;
		outline: none;
	}

	.title-input::placeholder {
		color: var(--rs-text-muted, #64748b);
	}

	.desc-input {
		background: transparent;
		border: none;
		color: var(--rs-text-secondary, #cbd5e1);
		font-size: 11px;
		width: 100%;
		outline: none;
		resize: none;
		min-height: 24px;
	}

	.desc-input::placeholder {
		color: var(--rs-text-muted, #475569);
	}

	.status-select {
		background: rgba(255, 255, 255, 0.06);
		border: 1px solid rgba(255, 255, 255, 0.1);
		border-radius: 4px;
		color: var(--rs-text-primary, #e2e8f0);
		font-size: 11px;
		padding: 3px 6px;
		outline: none;
		width: fit-content;
	}

	.progress-section {
		margin-top: 4px;
	}

	.progress-summary {
		display: flex;
		justify-content: space-between;
		font-size: 12px;
		font-weight: 600;
		color: var(--rs-text-primary, #e2e8f0);
		margin-bottom: 4px;
	}

	.progress-wrap {
		position: relative;
		height: 16px;
		background: rgba(255, 255, 255, 0.08);
		border-radius: 8px;
		overflow: hidden;
	}

	.progress-bar {
		height: 100%;
		border-radius: 8px;
		transition: width 0.3s, background 0.3s;
		background: ${HEADER_COLOR};
	}

	.progress-bar.complete {
		background: #22c55e;
		box-shadow: 0 0 8px rgba(34, 197, 94, 0.4);
	}

	.checklist {
		display: flex;
		flex-direction: column;
		gap: 3px;
		margin-top: 6px;
	}

	.check-item {
		display: flex;
		align-items: center;
		gap: 6px;
		font-size: 11px;
		color: var(--rs-text-secondary, #94a3b8);
		padding: 3px 6px;
		border-radius: 4px;
		background: rgba(255, 255, 255, 0.03);
	}

	.check-item.satisfied {
		color: #22c55e;
	}

	.check-icon {
		width: 14px;
		text-align: center;
		font-size: 10px;
	}

	.no-gates {
		font-size: 11px;
		color: var(--rs-text-muted, #475569);
		font-style: italic;
		text-align: center;
		padding: 12px 0;
	}
`;

declare global {
	interface HTMLElementTagNameMap {
		"folk-gov-project": FolkGovProject;
	}
}

export class FolkGovProject extends FolkShape {
	static override tagName = "folk-gov-project";

	static override portDescriptors: PortDescriptor[] = [
		{ name: "circuit-out", type: "json", direction: "output" },
	];

	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;
	}

	#title = "Project";
	#description = "";
	#status: ProjectStatus = "draft";
	#pollInterval: ReturnType<typeof setInterval> | null = null;

	// DOM refs
	#titleEl!: HTMLInputElement;
	#descEl!: HTMLTextAreaElement;
	#statusEl!: HTMLSelectElement;
	#summaryEl!: HTMLElement;
	#progressBar!: HTMLElement;
	#checklistEl!: HTMLElement;

	get title() { return this.#title; }
	set title(v: string) {
		this.#title = v;
		if (this.#titleEl) this.#titleEl.value = v;
	}

	get description() { return this.#description; }
	set description(v: string) {
		this.#description = v;
		if (this.#descEl) this.#descEl.value = v;
	}

	get status(): ProjectStatus { return this.#status; }
	set status(v: ProjectStatus) {
		this.#status = v;
		if (this.#statusEl) this.#statusEl.value = v;
	}

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

		const wrapper = document.createElement("div");
		wrapper.style.cssText = "width:100%;height:100%;display:flex;flex-direction:column;";
		wrapper.innerHTML = html`
			<div class="header" data-drag>
				<span class="header-title">🏗️ Project</span>
				<span class="header-actions">
					<button class="close-btn">&times;</button>
				</span>
			</div>
			<div class="body">
				<input class="title-input" type="text" placeholder="Project title..." />
				<textarea class="desc-input" placeholder="Description..." rows="2"></textarea>
				<select class="status-select">
					<option value="draft">Draft</option>
					<option value="active">Active</option>
					<option value="completed">Completed</option>
					<option value="archived">Archived</option>
				</select>
				<div class="progress-section">
					<div class="progress-summary">
						<span class="summary-text">0 of 0 gates</span>
					</div>
					<div class="progress-wrap">
						<div class="progress-bar" style="width: 0%"></div>
					</div>
					<div class="checklist"></div>
				</div>
			</div>
		`;

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

		// Cache refs
		this.#titleEl = wrapper.querySelector(".title-input") as HTMLInputElement;
		this.#descEl = wrapper.querySelector(".desc-input") as HTMLTextAreaElement;
		this.#statusEl = wrapper.querySelector(".status-select") as HTMLSelectElement;
		this.#summaryEl = wrapper.querySelector(".summary-text") as HTMLElement;
		this.#progressBar = wrapper.querySelector(".progress-bar") as HTMLElement;
		this.#checklistEl = wrapper.querySelector(".checklist") as HTMLElement;

		// Set initial values
		this.#titleEl.value = this.#title;
		this.#descEl.value = this.#description;
		this.#statusEl.value = this.#status;

		// Wire events
		const onChange = () => this.dispatchEvent(new CustomEvent("content-change"));

		this.#titleEl.addEventListener("input", (e) => {
			e.stopPropagation();
			this.#title = this.#titleEl.value;
			onChange();
		});

		this.#descEl.addEventListener("input", (e) => {
			e.stopPropagation();
			this.#description = this.#descEl.value;
			onChange();
		});

		this.#statusEl.addEventListener("change", (e) => {
			e.stopPropagation();
			this.#status = this.#statusEl.value as ProjectStatus;
			onChange();
		});

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

		// Prevent drag on inputs
		for (const el of wrapper.querySelectorAll("input, textarea, select, button")) {
			el.addEventListener("pointerdown", (e) => e.stopPropagation());
		}

		// Poll upstream gates every 2 seconds (pull-based)
		this.#pollInterval = setInterval(() => this.#scanUpstreamGates(), 2000);
		// Also scan immediately
		requestAnimationFrame(() => this.#scanUpstreamGates());

		return root;
	}

	override disconnectedCallback() {
		super.disconnectedCallback();
		if (this.#pollInterval) {
			clearInterval(this.#pollInterval);
			this.#pollInterval = null;
		}
	}

	/**
	 * Walk the arrow graph backward from this shape to find all upstream
	 * governance gates. Returns GateInfo[] for each discovered gate.
	 */
	#scanUpstreamGates(): void {
		const gates: GateInfo[] = [];
		const visited = new Set<string>();
		const queue: string[] = [this.id];

		// Find all arrows in the document
		const arrows = document.querySelectorAll("folk-arrow");

		while (queue.length > 0) {
			const currentId = queue.shift()!;
			if (visited.has(currentId)) continue;
			visited.add(currentId);

			// Find arrows targeting this shape
			for (const arrow of arrows) {
				const a = arrow as any;
				if (a.targetId === currentId) {
					const sourceId = a.sourceId;
					if (!sourceId || visited.has(sourceId)) continue;

					const sourceEl = document.getElementById(sourceId) as any;
					if (!sourceEl) continue;

					const tagName = sourceEl.tagName?.toUpperCase();
					if (GOV_TAG_NAMES.has(tagName)) {
						const portVal = sourceEl.getPortValue?.("gate-out");
						gates.push({
							id: sourceId,
							tagName,
							title: sourceEl.title || sourceEl.getAttribute?.("title") || tagName,
							satisfied: portVal?.satisfied === true,
						});
					}

					queue.push(sourceId);
				}
			}
		}

		this.#renderGates(gates);
	}

	#renderGates(gates: GateInfo[]) {
		const total = gates.length;
		const completed = gates.filter(g => g.satisfied).length;
		const pct = total > 0 ? (completed / total) * 100 : 0;
		const allDone = total > 0 && completed === total;

		// Auto-detect completion
		if (allDone && this.#status === "active") {
			this.#status = "completed";
			if (this.#statusEl) this.#statusEl.value = "completed";
			this.dispatchEvent(new CustomEvent("content-change"));
		}

		if (this.#summaryEl) {
			this.#summaryEl.textContent = `${completed} of ${total} gates`;
		}

		if (this.#progressBar) {
			this.#progressBar.style.width = `${pct}%`;
			this.#progressBar.classList.toggle("complete", allDone);
		}

		if (this.#checklistEl) {
			if (total === 0) {
				this.#checklistEl.innerHTML = `<div class="no-gates">Connect gov gates upstream to track progress</div>`;
			} else {
				this.#checklistEl.innerHTML = gates.map(g => {
					const icon = g.satisfied ? "✓" : "○";
					const cls = g.satisfied ? "check-item satisfied" : "check-item";
					const typeLabel = g.tagName.replace("FOLK-GOV-", "").toLowerCase();
					return `<div class="${cls}"><span class="check-icon">${icon}</span><span>${g.title} <small>(${typeLabel})</small></span></div>`;
				}).join("");
			}
		}

		// Emit port
		this.setPortValue("circuit-out", {
			status: this.#status,
			completedGates: completed,
			totalGates: total,
			percentage: pct,
		});
	}

	override toJSON() {
		return {
			...super.toJSON(),
			type: "folk-gov-project",
			title: this.#title,
			description: this.#description,
			status: this.#status,
		};
	}

	static override fromData(data: Record<string, any>): FolkGovProject {
		const shape = FolkShape.fromData.call(this, data) as FolkGovProject;
		if (data.title !== undefined) shape.title = data.title;
		if (data.description !== undefined) shape.description = data.description;
		if (data.status !== undefined) shape.status = data.status;
		return shape;
	}

	override applyData(data: Record<string, any>): void {
		super.applyData(data);
		if (data.title !== undefined && data.title !== this.#title) this.title = data.title;
		if (data.description !== undefined && data.description !== this.#description) this.description = data.description;
		if (data.status !== undefined && data.status !== this.#status) this.status = data.status;
	}
}
