/**
 * rTime applet definitions — Commitment Meter + Weaving Coverage.
 */

import type { AppletDefinition, AppletLiveData } from "../../shared/applet-types";
import { getModuleApiBase } from "../../shared/url-helpers";

const commitmentMeter: AppletDefinition = {
	id: "commitment-meter",
	label: "Commitment Meter",
	icon: "⏳",
	accentColor: "#7c3aed",
	ports: [
		{ name: "pool-in", type: "json", direction: "input" },
		{ name: "committed-out", type: "number", direction: "output" },
	],
	renderCompact(data: AppletLiveData): string {
		const { snapshot } = data;
		const committed = (snapshot.committed as number) || 0;
		const capacity = (snapshot.capacity as number) || 1;
		const pct = Math.min(100, Math.round((committed / capacity) * 100));
		const label = (snapshot.poolName as string) || "Pool";

		return `
			<div style="text-align:center">
				<div style="font-size:13px;font-weight:600;margin-bottom:6px">${label}</div>
				<div style="font-size:24px;font-weight:700;color:#e2e8f0">${pct}%</div>
				<div style="font-size:10px;color:#94a3b8;margin:4px 0 8px">${committed}/${capacity} hrs</div>
				<div style="background:#334155;border-radius:3px;height:6px;overflow:hidden">
					<div style="background:#7c3aed;width:${pct}%;height:100%;border-radius:3px;transition:width 0.3s"></div>
				</div>
			</div>
		`;
	},
	onInputReceived(portName, value, ctx) {
		if (portName === "pool-in" && value && typeof value === "object") {
			const pool = value as Record<string, unknown>;
			ctx.emitOutput("committed-out", Number(pool.committed) || 0);
		}
	},
};

// ── Weaving Coverage ──

interface WeavePlacedTask {
	id: string;
	title: string;
	status: string;
	needs: Record<string, number>;
}

interface WeaveData {
	placedTasks?: WeavePlacedTask[];
	connections?: Array<{ commitmentId: string; taskId: string; skill: string; hours: number }>;
}

const SKILL_COLORS: Record<string, string> = {
	facilitation: '#8b5cf6', design: '#ec4899', tech: '#3b82f6',
	outreach: '#10b981', logistics: '#f59e0b',
};

const weavingCoverage: AppletDefinition = {
	id: "weaving-coverage",
	label: "Weaving Coverage",
	icon: "🧶",
	accentColor: "#7c3aed",
	ports: [
		{ name: "pool-in", type: "json", direction: "input" },
		{ name: "coverage-out", type: "json", direction: "output" },
	],

	async fetchLiveData(space: string): Promise<Record<string, unknown>> {
		try {
			const resp = await fetch(`${getModuleApiBase("rtime")}/api/weave`);
			if (!resp.ok) return {};
			const data: WeaveData = await resp.json();
			return buildCoverageSnapshot(data);
		} catch { return {}; }
	},

	renderCompact(data: AppletLiveData): string {
		const { snapshot } = data;
		const tasks = (snapshot.tasks as Array<{ id: string; title: string; ready: boolean; partial: boolean; needs: Record<string, number>; fulfilled: Record<string, number> }>) || [];
		const summary = (snapshot.summary as { total: number; ready: number; partial: number }) || { total: 0, ready: 0, partial: 0 };

		if (tasks.length === 0) {
			return `<div style="text-align:center;color:#64748b;font-style:italic;padding:16px 0">No tasks on weaving canvas</div>`;
		}

		let html = `<div style="font-size:10px;color:#94a3b8;margin-bottom:6px">${summary.ready}/${summary.total} tasks resourced</div>`;
		for (const t of tasks.slice(0, 5)) {
			const skills = Object.keys(t.needs);
			let bars = '';
			for (const sk of skills) {
				const need = t.needs[sk] || 1;
				const got = (t.fulfilled?.[sk]) || 0;
				const pct = Math.min(100, Math.round((got / need) * 100));
				const color = SKILL_COLORS[sk] || '#6b7280';
				bars += `<div style="display:flex;align-items:center;gap:4px;margin:1px 0">
					<span style="width:50px;font-size:8px;color:${color};text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${sk}</span>
					<div style="flex:1;background:#1e293b;border-radius:2px;height:4px;overflow:hidden">
						<div style="background:${color};width:${pct}%;height:100%;border-radius:2px"></div>
					</div>
					<span style="font-size:8px;color:#64748b;width:24px">${got}/${need}</span>
				</div>`;
			}
			const statusColor = t.ready ? '#22c55e' : t.partial ? '#f59e0b' : '#64748b';
			html += `<div style="margin-bottom:6px;padding:4px 6px;background:#0f172a;border-radius:4px;border-left:2px solid ${statusColor}">
				<div style="font-size:10px;font-weight:600;color:#e2e8f0;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${t.title}</div>
				${bars}
			</div>`;
		}
		if (tasks.length > 5) {
			html += `<div style="font-size:9px;color:#64748b;text-align:center">+${tasks.length - 5} more</div>`;
		}
		return html;
	},

	onInputReceived(portName, value, ctx) {
		if (portName === "pool-in") {
			// Pool data received — re-fetch would be ideal but for now just trigger output
			// The fetchLiveData polling handles refresh
		}
	},
};

function buildCoverageSnapshot(data: WeaveData): Record<string, unknown> {
	const placed = data.placedTasks || [];
	const connections = data.connections || [];

	// Build fulfillment map: taskId → skill → hours fulfilled
	const fulfillment = new Map<string, Record<string, number>>();
	for (const conn of connections) {
		if (!fulfillment.has(conn.taskId)) fulfillment.set(conn.taskId, {});
		const tf = fulfillment.get(conn.taskId)!;
		tf[conn.skill] = (tf[conn.skill] || 0) + conn.hours;
	}

	const tasks = placed.map(t => {
		const needs = t.needs || {};
		const fulfilled = fulfillment.get(t.id) || {};
		const skills = Object.keys(needs);
		const allFilled = skills.length > 0 && skills.every(sk => (fulfilled[sk] || 0) >= needs[sk]);
		const someFilled = skills.some(sk => (fulfilled[sk] || 0) > 0);
		return {
			id: t.id,
			title: t.title,
			needs,
			fulfilled,
			ready: allFilled,
			partial: !allFilled && someFilled,
		};
	});

	const ready = tasks.filter(t => t.ready).length;
	const partial = tasks.filter(t => t.partial).length;

	return {
		tasks,
		summary: { total: tasks.length, ready, partial },
	};
}

export const timeApplets: AppletDefinition[] = [commitmentMeter, weavingCoverage];
