/**
 * Frontend mirror of the Rust typed RPC contract in
 * `server/src/crdt_sync/rpc_contract.rs`.
 *
 * Every typed write method declared on the backend has matching TypeScript
 * params/result types here.  The `CONTRACT_FIXTURES` table also exposes the
 * same canonical example payloads as the Rust `CONTRACT_METHODS` slice — the
 * `rpcContract.test.ts` test compares them against the committed
 * `rpcContract.snapshot.json` that the Rust test regenerates.  If the Rust
 * shapes drift from the TS shapes, the snapshot drifts and one side fails in
 * CI — surfacing the mismatch as a compile / test error instead of a runtime
 * one.
 *
 * When adding a method on the backend:
 *  1. Add the params + result type here.
 *  2. Add the entry to `CONTRACT_FIXTURES` with a canonical example.
 *  3. Re-run `UPDATE_RPC_CONTRACT_SNAPSHOT=1 cargo test` to refresh
 *     `rpcContract.snapshot.json`.
 */

// ── Params types ────────────────────────────────────────────────────────────

/** Params for `model.set_preference`. */
export interface SetModelPreferenceParams {
	model: string;
}

/** Params for `anthropic.set_api_key`. */
export interface SetAnthropicApiKeyParams {
	api_key: string;
}

/** Params for `settings.put_editor`. */
export interface PutEditorParams {
	editor_command: string | null;
}

/** Params for `settings.open_file`. */
export interface OpenFileParams {
	path: string;
	line: number | null;
}

/** Params for `project.open`. */
export interface OpenProjectParams {
	path: string;
}

/** Params for `project.forget`. */
export interface ForgetProjectParams {
	path: string;
}

/** Payload for `bot_config.save` (and result of `bot_config.get`). */
export interface BotConfigPayload {
	transport: string | null;
	enabled: boolean | null;
	homeserver: string | null;
	username: string | null;
	password: string | null;
	room_ids: string[] | null;
	slack_bot_token: string | null;
	slack_signing_secret: string | null;
	slack_channel_ids: string[] | null;
}

/** Payload for `settings.put_project` (also returned by `settings.get_project`). */
export interface ProjectSettingsPayload {
	default_qa: string;
	default_coder_model: string | null;
	max_coders: number | null;
	max_retries: number;
	base_branch: string | null;
	rate_limit_notifications: boolean;
	timezone: string | null;
	rendezvous: string | null;
	watcher_sweep_interval_secs: number;
	watcher_done_retention_secs: number;
}

// ── Result types ────────────────────────────────────────────────────────────

/** Result envelope for write methods that simply succeed or fail. */
export interface OkResult {
	ok: boolean;
}

/** Result for `settings.put_editor`. */
export interface EditorSettingsResult {
	editor_command: string | null;
}

/** Result for `project.open`. */
export interface OpenProjectResult {
	path: string;
}

// ── Method → params/result mapping ──────────────────────────────────────────

/**
 * Compile-time mapping from typed RPC method name to its params + result
 * shapes.  Used by `callTypedRpc` to enforce that callers pass the right
 * params and receive the right return type for a method.
 */
export interface TypedRpcMethods {
	"model.set_preference": {
		params: SetModelPreferenceParams;
		result: OkResult;
	};
	"anthropic.set_api_key": {
		params: SetAnthropicApiKeyParams;
		result: OkResult;
	};
	"settings.put_editor": {
		params: PutEditorParams;
		result: EditorSettingsResult;
	};
	"settings.open_file": {
		params: OpenFileParams;
		result: OkResult;
	};
	"settings.put_project": {
		params: ProjectSettingsPayload;
		result: ProjectSettingsPayload;
	};
	"project.open": {
		params: OpenProjectParams;
		result: OpenProjectResult;
	};
	"project.close": {
		params: Record<string, never>;
		result: OkResult;
	};
	"project.forget": {
		params: ForgetProjectParams;
		result: OkResult;
	};
	"bot_config.save": {
		params: BotConfigPayload;
		result: BotConfigPayload;
	};
	"chat.cancel": {
		params: Record<string, never>;
		result: OkResult;
	};
}

/** Union of all typed RPC method names declared in the contract. */
export type TypedRpcMethodName = keyof TypedRpcMethods;

// ── Canonical fixtures (mirror of Rust `CONTRACT_METHODS`) ──────────────────

/**
 * One canonical example payload per typed RPC method.  The shape *must*
 * match the corresponding Rust `CONTRACT_METHODS` entry.  Drift between this
 * table and `rpcContract.snapshot.json` (regenerated by the Rust side) fails
 * the `rpcContract.test.ts` snapshot check.
 */
export const CONTRACT_FIXTURES: {
	[K in TypedRpcMethodName]: {
		params: TypedRpcMethods[K]["params"];
		result: TypedRpcMethods[K]["result"];
	};
} = {
	"model.set_preference": {
		params: { model: "claude-sonnet-4-6" },
		result: { ok: true },
	},
	"anthropic.set_api_key": {
		params: { api_key: "sk-ant-..." },
		result: { ok: true },
	},
	"settings.put_editor": {
		params: { editor_command: "zed" },
		result: { editor_command: "zed" },
	},
	"settings.open_file": {
		params: { path: "src/main.rs", line: 42 },
		result: { ok: true },
	},
	"settings.put_project": {
		params: {
			default_qa: "server",
			default_coder_model: null,
			max_coders: null,
			max_retries: 2,
			base_branch: null,
			rate_limit_notifications: true,
			timezone: null,
			rendezvous: null,
			watcher_sweep_interval_secs: 60,
			watcher_done_retention_secs: 86_400,
		},
		result: {
			default_qa: "server",
			default_coder_model: null,
			max_coders: null,
			max_retries: 2,
			base_branch: null,
			rate_limit_notifications: true,
			timezone: null,
			rendezvous: null,
			watcher_sweep_interval_secs: 60,
			watcher_done_retention_secs: 86_400,
		},
	},
	"project.open": {
		params: { path: "/path/to/project" },
		result: { path: "/path/to/project" },
	},
	"project.close": {
		params: {},
		result: { ok: true },
	},
	"project.forget": {
		params: { path: "/path/to/project" },
		result: { ok: true },
	},
	"bot_config.save": {
		params: {
			transport: "matrix",
			enabled: true,
			homeserver: "https://matrix.example",
			username: "bot",
			password: "secret",
			room_ids: ["!room:example"],
			slack_bot_token: null,
			slack_signing_secret: null,
			slack_channel_ids: null,
		},
		result: {
			transport: "matrix",
			enabled: true,
			homeserver: "https://matrix.example",
			username: "bot",
			password: "secret",
			room_ids: ["!room:example"],
			slack_bot_token: null,
			slack_signing_secret: null,
			slack_channel_ids: null,
		},
	},
	"chat.cancel": {
		params: {},
		result: { ok: true },
	},
};
