/**
 * rCred module — Contribution Recognition via CredRank.
 *
 * Builds a per-space contribution graph from all module activity,
 * runs CredRank (modified PageRank on weighted contribution edges),
 * and distributes Grain tokens proportional to contribution.
 *
 * Inspired by SourceCred (RIP 2018–2022) — algorithm lives on.
 */

import { Hono } from 'hono';
import { renderShell } from '../../server/shell';
import { getModuleInfoList } from '../../shared/module';
import type { RSpaceModule } from '../../shared/module';
import type { SyncServer } from '../../server/local-first/sync-server';
import { graphSchema, scoresSchema, configSchema, configDocId, scoresDocId } from './schemas';
import type { CredConfigDoc } from './schemas';
import { createCredRoutes } from './routes';
import { recomputeSpace, ensureConfigDoc } from './grain-engine';
import { renderLanding } from './landing';

let _syncServer: SyncServer | null = null;

const routes = new Hono();

// Mount API routes
const apiRoutes = createCredRoutes(() => _syncServer);

routes.route('/', apiRoutes);

// ── Landing page ──
routes.get('/', (c) => {
	const space = c.req.param('space');
	return c.html(
		renderShell({
			title: 'rCred — Contribution Recognition',
			spaceSlug: space || 'demo',
			moduleId: 'rcred',
			modules: getModuleInfoList(),
			body: `<folk-cred-dashboard space="${space || 'demo'}"></folk-cred-dashboard>`,
			scripts: '<script type="module" src="/modules/rcred/folk-cred-dashboard.js?v=1"></script>',
		}),
	);
});

// ── Cron: recompute every 6 hours ──
const CRON_INTERVAL = 6 * 60 * 60 * 1000; // 6h
let cronTimer: ReturnType<typeof setInterval> | null = null;

function startCredCron() {
	if (cronTimer) return;
	cronTimer = setInterval(() => {
		if (!_syncServer) return;
		const allDocs = _syncServer.listDocs();
		const configDocs = allDocs.filter(id => id.endsWith(':rcred:config'));
		for (const docId of configDocs) {
			const space = docId.split(':')[0];
			if (!space) continue;
			const config = _syncServer.getDoc<CredConfigDoc>(docId);
			if (!config?.enabled) continue;

			// Check epoch timing
			const epochMs = (config.epochLengthDays || 7) * 86_400_000;
			if (Date.now() - (config.lastEpochAt || 0) < epochMs) continue;

			console.log(`[rCred cron] Recomputing ${space}...`);
			recomputeSpace(space, _syncServer);
		}
	}, CRON_INTERVAL);
}

export const credModule: RSpaceModule = {
	id: 'rcred',
	name: 'rCred',
	icon: '⭐',
	description: 'Contribution recognition — Cred scores + Grain distribution via CredRank',
	routes,

	publicWrite: true, // recompute route handles its own auth
	scoping: { defaultScope: 'space', userConfigurable: false },
	docSchemas: [graphSchema, scoresSchema, configSchema],

	onInit: async ({ syncServer }) => {
		_syncServer = syncServer;
		startCredCron();
		console.log('[rCred] Module initialized, cron started (6h interval)');

		// Auto-seed demo space on startup (delayed to let docs load)
		setTimeout(() => {
			if (!_syncServer) return;
			const scores = _syncServer.getDoc(scoresDocId('demo'));
			if (!scores) {
				console.log('[rCred] Seeding demo space scores...');
				recomputeSpace('demo', _syncServer);
			}
		}, 10_000);
	},

	feeds: [
		{
			id: 'rcred-scores',
			name: 'Cred Scores',
			description: 'CredRank contribution scores per space member',
			kind: 'trust',
		},
	],

	landingPage: renderLanding,

	settingsSchema: [
		{
			key: 'enabled',
			label: 'Enable CredRank',
			type: 'boolean',
			description: 'Enable automatic contribution scoring and grain distribution',
			default: true,
		},
		{
			key: 'grainPerEpoch',
			label: 'Grain per Epoch',
			type: 'string',
			description: 'Amount of GRAIN tokens distributed each epoch (default: 1000)',
			default: '1000',
		},
		{
			key: 'lookbackDays',
			label: 'Lookback Window (days)',
			type: 'string',
			description: 'How far back to look for contributions (default: 90)',
			default: '90',
		},
	],
};
