/**
 * rVote Automerge document schemas.
 *
 * Granularity: one Automerge document per proposal.
 * DocId format: {space}:vote:proposals:{proposalId}
 *
 * Vote tallying uses the Intent/Claim pattern:
 * clients submit vote intents, server validates and writes claims.
 */

import type { DocSchema } from '../../shared/local-first/document';

// ── Document types ──

export interface VoteItem {
	id: string;
	userId: string;
	proposalId: string;
	weight: number;
	creditCost: number;
	createdAt: number;
	decaysAt: number;
}

export interface FinalVoteItem {
	id: string;
	userId: string;
	proposalId: string;
	vote: 'YES' | 'NO' | 'ABSTAIN';
	createdAt: number;
}

export interface SpaceConfig {
	slug: string;
	name: string;
	description: string;
	ownerDid: string;
	visibility: string;
	promotionThreshold: number | null;
	votingPeriodDays: number | null;
	creditsPerDay: number | null;
	maxCredits: number | null;
	startingCredits: number | null;
	createdAt: number;
	updatedAt: number;
}

export interface ProposalMeta {
	id: string;
	spaceSlug: string;
	authorId: string;
	title: string;
	description: string;
	status: string;
	score: number;
	votingEndsAt: number;
	finalYes: number;
	finalNo: number;
	finalAbstain: number;
	createdAt: number;
	updatedAt: number;
}

export interface PairwiseData {
	elo: number;           // Current Elo rating (default 1500)
	comparisons: number;   // Total times shown in a pair
	wins: number;          // Times chosen as preferred
}

export interface ProposalDoc {
	meta: {
		module: string;
		collection: string;
		version: number;
		spaceSlug: string;
		createdAt: number;
	};
	spaceConfig: SpaceConfig | null;
	proposal: ProposalMeta;
	votes: Record<string, VoteItem>;
	finalVotes: Record<string, FinalVoteItem>;
	pairwise: PairwiseData;
}

// ── Elo rating helpers ──

export const ELO_K = 32;
export const ELO_DEFAULT = 1500;

export function computeElo(winnerElo: number, loserElo: number): { winner: number; loser: number } {
	const expected = 1 / (1 + Math.pow(10, (loserElo - winnerElo) / 400));
	const delta = Math.round(ELO_K * (1 - expected));
	return { winner: winnerElo + delta, loser: loserElo - delta };
}

// ── Schema registration ──

export const proposalSchema: DocSchema<ProposalDoc> = {
	module: 'vote',
	collection: 'proposals',
	version: 1,
	init: (): ProposalDoc => ({
		meta: {
			module: 'vote',
			collection: 'proposals',
			version: 1,
			spaceSlug: '',
			createdAt: Date.now(),
		},
		spaceConfig: null,
		proposal: {
			id: '',
			spaceSlug: '',
			authorId: '',
			title: '',
			description: '',
			status: 'RANKING',
			score: 0,
			votingEndsAt: 0,
			finalYes: 0,
			finalNo: 0,
			finalAbstain: 0,
			createdAt: Date.now(),
			updatedAt: Date.now(),
		},
		votes: {},
		finalVotes: {},
		pairwise: { elo: ELO_DEFAULT, comparisons: 0, wins: 0 },
	}),
};

// ── Helpers ──

export function proposalDocId(space: string, proposalId: string) {
	return `${space}:vote:proposals:${proposalId}` as const;
}
