import type { ClientPrefix, ClientPrefixInput } from "@/lib/types";

export interface PrefixRow {
	prefix: string;
	group_id: number;
	/** Raw input text; empty means "use the server default (100)". */
	priority: string;
}

export interface PrefixEditorState {
	baseline: PrefixRow[];
	rows: PrefixRow[];
}

export type PrefixEditorAction =
	| { type: "reset"; prefixes: ClientPrefix[] }
	| { type: "add"; groupId: number }
	| { type: "remove"; index: number }
	| { type: "edit"; index: number; patch: Partial<PrefixRow> };

function fromServer(prefixes: ClientPrefix[]): PrefixRow[] {
	return prefixes.map((p) => ({ prefix: p.prefix, group_id: p.group_id, priority: String(p.priority) }));
}

export function initPrefixEditor(prefixes: ClientPrefix[]): PrefixEditorState {
	const rows = fromServer(prefixes);
	return { baseline: rows, rows };
}

export function prefixEditorReducer(state: PrefixEditorState, action: PrefixEditorAction): PrefixEditorState {
	switch (action.type) {
		case "reset":
			return initPrefixEditor(action.prefixes);
		case "add":
			return { ...state, rows: [...state.rows, { prefix: "", group_id: action.groupId, priority: "" }] };
		case "remove":
			return { ...state, rows: state.rows.filter((_, i) => i !== action.index) };
		case "edit":
			return {
				...state,
				rows: state.rows.map((row, i) => (i === action.index ? { ...row, ...action.patch } : row)),
			};
	}
}

function sameRow(a: PrefixRow, b: PrefixRow): boolean {
	return a.prefix === b.prefix && a.group_id === b.group_id && a.priority === b.priority;
}

export function isDirty(state: PrefixEditorState): boolean {
	if (state.rows.length !== state.baseline.length) return true;
	return state.rows.some((row, i) => {
		const base = state.baseline[i];
		return base === undefined || !sameRow(row, base);
	});
}

/** Which input the message is about, so the editor can point that input at it. */
export interface PrefixProblem {
	index: number;
	field: "prefix" | "priority";
	message: string;
}

export function firstProblem(rows: PrefixRow[]): PrefixProblem | null {
	for (const [index, row] of rows.entries()) {
		if (row.prefix.trim() === "")
			return { index, field: "prefix", message: `Row ${index + 1}: prefix is required.` };
		const priority = row.priority.trim();
		if (priority !== "" && !/^\d+$/.test(priority))
			return { index, field: "priority", message: `Row ${index + 1}: priority must be a whole number.` };
	}
	return null;
}

export function toInputs(rows: PrefixRow[]): ClientPrefixInput[] {
	return rows.map((row) => {
		const input: ClientPrefixInput = { prefix: row.prefix.trim(), group_id: row.group_id };
		const priority = row.priority.trim();
		if (priority !== "") input.priority = Number(priority);
		return input;
	});
}
