export type Models = {
	agi_prior_message: {
		channel_id: string
		username: string
		avatar_url: string
		use_caps: number
		use_punct: number
		use_apos: number
		timestamp: number
	}

	agi_optout: {
		guild_id: string
	}

	agi_cooldown: {
		guild_id: string
		timestamp: number
	}

	app_user_install: {
		guild_id: string
		app_bot_id: string
		user_id: string
	}

	auto_emoji: {
		name: string
		emoji_id: string
	}

	channel_room: {
		channel_id: string
		room_id: string
		name: string
		nick: string | null
		thread_parent: string | null
		custom_avatar: string | null
		last_bridged_pin_timestamp: number | null
		speedbump_id: string | null
		speedbump_webhook_id: string | null
		speedbump_checked: number | null
		guild_id: string | null
		custom_topic: number
	}

	direct: {
		mxid: string
		room_id: string
	}

	emoji: {
		emoji_id: string
		name: string
		animated: number
		mxc_url: string
	}

	event_message: {
		event_id: string
		message_id: string
		event_type: string | null
		event_subtype: string | null
		part: number
		reaction_part: number
		source: number
	}

	file: {
		discord_url: string
		mxc_url: string
	}

	guild_space: {
		guild_id: string
		space_id: string
		privacy_level: number
		presence: 0 | 1
		url_preview: 0 | 1
		webhook_profile: 0 | 1
	}

	guild_active: {
		guild_id: string
		autocreate: 0 | 1
	}

	historical_channel_room: {
		historical_room_index: number
		reference_channel_id: string
		room_id: string
		upgraded_timestamp: number
	}

	invite: {
		mxid: string
		room_id: string
		type: string | null
		name: string | null
		avatar: string | null
	}

	lottie: {
		sticker_id: string
		mxc_url: string
	}

	media_proxy: {
		permitted_hash: number
	}

	member_cache: {
		room_id: string
		mxid: string
		displayname: string | null
		avatar_url: string | null,
		power_level: number
		missing_profile: number | null
	}

	member_power: {
		mxid: string
		room_id: string
		power_level: number
	}

	message_room: {
		message_id: string
		historical_room_index: number
	}

	role_default: {
		guild_id: string
		role_id: string
	}

	room_upgrade_pending: {
		new_room_id: string
		old_room_id: string
	}

	sim: {
		user_id: string
		username: string
		sim_name: string
		mxid: string
	}

	sim_member: {
		mxid: string
		room_id: string
		hashed_profile_content: number
	}

	sim_proxy: {
		user_id: string
		proxy_owner_id: string
		displayname: string
	}

	webhook: {
		channel_id: string
		webhook_id: string
		webhook_token: string
	}

	reaction: {
		hashed_event_id: number
		message_id: string
		encoded_emoji: string
		original_encoding: string | null
	}

	poll: { // not actually in database yet
		message_id: string
		max_selections: number
		question_text: string
		is_closed: number
	}

	poll_option: {
		message_id: string
		matrix_option: string
		discord_option: string | null
		option_text: string // not actually in database yet
		seq: number // not actually in database yet
	}

	poll_vote: {
		message_id: string
		matrix_option: string
		discord_or_matrix_user_id: string
	}
}

export type Prepared<Row> = {
	pluck: () => Prepared<Row[keyof Row]>
	safeIntegers: () => Prepared<{[K in keyof Row]: Row[K] extends number ? BigInt : Row[K]}>
	raw: () => Prepared<Row[keyof Row][]>
	all: (..._: any[]) => Row[]
	get: (..._: any[]) => Row | null | undefined
}

export type AllKeys<U> = U extends any ? keyof U : never
export type PickTypeOf<T, K extends AllKeys<T>> = T extends { [k in K]?: any } ? T[K] : never
export type Merge<U> = {[x in AllKeys<U>]: PickTypeOf<U, x>}
export type Nullable<T> = {[k in keyof T]: T[k] | null}
export type Numberish<T> = {[k in keyof T]: T[k] extends number ? (number | bigint) : T[k]}
export type ValueOrArray<T> = {[k in keyof T]: T[k][] | T[k]}
