/**
 * Choices module — voting, ranking, and multi-criteria scoring tools.
 *
 * The folk-choice-* web components live in lib/ (shared with canvas).
 * This module provides:
 *  - A page listing choice shapes in the current space
 *  - API to query choice shapes from the Automerge store
 *  - Links to create new choices on the canvas
 */

import { Hono } from "hono";
import { renderShell } from "../../server/shell";
import type { RSpaceModule } from "../../shared/module";
import { renderLanding } from "./landing";
import { getModuleInfoList } from "../../shared/module";
import { getDocumentData, addShapes } from "../../server/community-store";
import { verifyToken, extractToken } from "../../server/auth";
import { syncServer } from "../../server/sync-instance";
import { choicesDocId } from "./schemas";
import type { ChoicesDoc } from "./schemas";
import { sendMagicLinks } from "../../server/magic-link/send";

const routes = new Hono();

// GET /api/choices — list choice shapes in the current space
routes.get("/api/choices", async (c) => {
	const space = c.req.param("space") || c.req.query("space") || "demo";
	const docData = getDocumentData(space);
	if (!docData?.shapes) {
		return c.json({ choices: [], total: 0 });
	}

	const choiceTypes = ["folk-choice-vote", "folk-choice-rank", "folk-choice-spider"];
	const choices: any[] = [];

	for (const [id, shape] of Object.entries(docData.shapes as Record<string, any>)) {
		if (shape.forgotten) continue;
		if (choiceTypes.includes(shape.type)) {
			choices.push({
				id,
				type: shape.type,
				title: shape.title || "Untitled",
				mode: shape.mode,
				optionCount: (shape.options || []).length,
				voteCount: (shape.votes || shape.rankings || shape.scores || []).length,
				createdAt: shape.createdAt,
			});
		}
	}

	return c.json({ choices, total: choices.length });
});

// POST /api/choices/:sessionId/invite — create magic links for a poll session
routes.post("/api/choices/:sessionId/invite", async (c) => {
	const authToken = extractToken(c.req.raw.headers);
	if (!authToken) return c.json({ error: "Authentication required" }, 401);
	try { await verifyToken(authToken); } catch { return c.json({ error: "Invalid token" }, 401); }

	const space = c.req.param("space") || "demo";
	const sessionId = c.req.param("sessionId");

	const doc = syncServer.getDoc<ChoicesDoc>(choicesDocId(space));
	if (!doc) return c.json({ error: "Choices doc not found" }, 404);
	const session = doc.sessions[sessionId];
	if (!session) return c.json({ error: "Session not found" }, 404);

	const body = await c.req.json<{ participants: Array<{ name: string; email: string }>; sendEmail?: boolean }>();
	if (!body.participants?.length) return c.json({ error: "participants array required" }, 400);

	const results = await sendMagicLinks({
		space,
		type: "poll",
		targetId: sessionId,
		title: session.title,
		participants: body.participants,
		sendEmail: body.sendEmail,
	});

	return c.json({ ok: true, invites: results });
});

// GET / — choices page (default tab: spider)
routes.get("/", (c) => {
	const spaceSlug = c.req.param("space") || "demo";
	return c.html(renderShell({
		title: `${spaceSlug} — Choices | rSpace`,
		moduleId: "rchoices",
		spaceSlug,
		modules: getModuleInfoList(),
		theme: "dark",
		body: `<folk-choices-dashboard space="${spaceSlug}" tab="spider"></folk-choices-dashboard>`,
		scripts: `<script type="module" src="/modules/rchoices/folk-choices-dashboard.js?v=7"></script>`,
		styles: `<link rel="stylesheet" href="/modules/rchoices/choices.css">`,
	}));
});

// GET /:tab — choices page with active sub-tab
routes.get("/:tab", (c) => {
	const spaceSlug = c.req.param("space") || "demo";
	const tab = c.req.param("tab");
	const validTabs = ["spider", "ranking", "voting", "crowdsurf"];
	if (!validTabs.includes(tab)) return c.notFound();
	const tabLabel = tab === "crowdsurf" ? "CrowdSurf" : tab.charAt(0).toUpperCase() + tab.slice(1);
	return c.html(renderShell({
		title: `${spaceSlug} — ${tabLabel} | rChoices`,
		moduleId: "rchoices",
		spaceSlug,
		modules: getModuleInfoList(),
		theme: "dark",
		body: `<folk-choices-dashboard space="${spaceSlug}" tab="${tab}"></folk-choices-dashboard>`,
		scripts: `<script type="module" src="/modules/rchoices/folk-choices-dashboard.js?v=7"></script>`,
		styles: `<link rel="stylesheet" href="/modules/rchoices/choices.css">`,
	}));
});

// ── Seed template data ──

function seedTemplateChoices(space: string) {
	// Check if space already has choice shapes
	const docData = getDocumentData(space);
	const choiceTypes = ["folk-choice-vote", "folk-choice-rank", "folk-choice-spider"];
	if (docData?.shapes) {
		const existing = Object.values(docData.shapes as Record<string, any>)
			.filter((s: any) => !s.forgotten && choiceTypes.includes(s.type));
		if (existing.length > 0) return;
	}

	const now = Date.now();
	const shapes: Record<string, unknown>[] = [
		{
			id: `tmpl-choice-vote-${now}`, type: 'folk-choice-vote',
			x: 50, y: 1800, width: 420, height: 360, rotation: 0,
			title: 'Governance Priority Vote',
			mode: 'plurality',
			options: [
				{ id: crypto.randomUUID(), label: 'Infrastructure improvements', color: '#3b82f6' },
				{ id: crypto.randomUUID(), label: 'Community education programs', color: '#8b5cf6' },
				{ id: crypto.randomUUID(), label: 'Open-source tooling grants', color: '#10b981' },
			],
			votes: [], createdAt: now,
		},
		{
			id: `tmpl-choice-rank-${now}`, type: 'folk-choice-rank',
			x: 520, y: 1800, width: 420, height: 360, rotation: 0,
			title: 'Sprint Priority Ranking',
			options: [
				{ id: crypto.randomUUID(), label: 'Dark mode across all modules' },
				{ id: crypto.randomUUID(), label: 'Mobile-responsive layouts' },
				{ id: crypto.randomUUID(), label: 'Offline-first sync' },
				{ id: crypto.randomUUID(), label: 'Notification system' },
			],
			rankings: [], createdAt: now,
		},
		{
			id: `tmpl-choice-spider-${now}`, type: 'folk-choice-spider',
			x: 990, y: 1800, width: 420, height: 360, rotation: 0,
			title: 'Team Skills Assessment',
			options: [
				{ id: crypto.randomUUID(), label: 'Frontend' },
				{ id: crypto.randomUUID(), label: 'Backend' },
				{ id: crypto.randomUUID(), label: 'Design' },
				{ id: crypto.randomUUID(), label: 'DevOps' },
				{ id: crypto.randomUUID(), label: 'Community' },
			],
			scores: [], createdAt: now,
		},
	];

	addShapes(space, shapes);
	console.log(`[Choices] Template seeded for "${space}": 3 choice shapes`);
}

// ── MI export ──

export function getRecentChoiceSessionsForMI(space: string, limit = 5): { id: string; title: string; type: string; optionCount: number; closed: boolean; createdAt: number }[] {
	const doc = syncServer.getDoc<ChoicesDoc>(choicesDocId(space));
	if (!doc) return [];
	return Object.values(doc.sessions)
		.sort((a, b) => b.createdAt - a.createdAt)
		.slice(0, limit)
		.map((s) => ({ id: s.id, title: s.title, type: s.type, optionCount: s.options?.length || 0, closed: !!s.closed, createdAt: s.createdAt }));
}

export const choicesModule: RSpaceModule = {
	id: "rchoices",
	name: "rChoices",
	icon: "☑",
	description: "Polls, rankings, and multi-criteria scoring",
	canvasShapes: ["folk-choice-vote", "folk-choice-rank", "folk-choice-spider", "folk-spider-3d", "folk-choice-conviction"],
	scoping: { defaultScope: 'space', userConfigurable: false },
	routes,
	standaloneDomain: "rchoices.online",
	landingPage: renderLanding,
	seedTemplate: seedTemplateChoices,
	feeds: [
		{
			id: "poll-results",
			name: "Poll Results",
			kind: "governance",
			description: "Live poll, ranking, and scoring outcomes",
			emits: ["folk-choice-vote", "folk-choice-rank", "folk-choice-spider"],
		},
	],
	acceptsFeeds: ["data", "governance"],
	outputPaths: [
		{ path: "spider", name: "Spider Chart", icon: "🕸", description: "Multi-criteria radar charts" },
		{ path: "ranking", name: "Ranking", icon: "📊", description: "Drag-and-drop rankings" },
		{ path: "voting", name: "Voting", icon: "☑", description: "Live polls and voting" },
		{ path: "crowdsurf", name: "CrowdSurf", icon: "🏄", description: "Swipe-based option surfacing" },
	],
};
