import type { BobbinContext, QueryValue, XrpcRequestInit } from "./client";
import { buildUrl, jsonGet, rawGet } from "./_request";
import type * as Archive from "./lexicons/types/sh/tangled/repo/archive";
import type * as Blob_ from "./lexicons/types/sh/tangled/repo/blob";
import type * as Branch from "./lexicons/types/sh/tangled/repo/branch";
import type * as Branches from "./lexicons/types/sh/tangled/repo/branches";
import type * as Compare from "./lexicons/types/sh/tangled/repo/compare";
import type * as DescribeRepo from "./lexicons/types/sh/tangled/repo/describeRepo";
import type * as Diff from "./lexicons/types/sh/tangled/repo/diff";
import type * as GetDefaultBranch from "./lexicons/types/sh/tangled/repo/getDefaultBranch";
import type * as Languages from "./lexicons/types/sh/tangled/repo/languages";
import type * as ListSecrets from "./lexicons/types/sh/tangled/repo/listSecrets";
import type * as Log from "./lexicons/types/sh/tangled/repo/log";
import type * as Tag from "./lexicons/types/sh/tangled/repo/tag";
import type * as Tags from "./lexicons/types/sh/tangled/repo/tags";
import type * as Tree from "./lexicons/types/sh/tangled/repo/tree";

// wrappers for bobbin's knot-proxied repo endpoints.

const asParams = (params: object): Record<string, QueryValue> =>
	params as unknown as Record<string, QueryValue>;

export const tree = (ctx: BobbinContext, params: Tree.$params, init?: XrpcRequestInit) =>
	jsonGet<Tree.$output>(ctx, "sh.tangled.repo.tree", asParams(params), init);

export const blob = (ctx: BobbinContext, params: Blob_.$params, init?: XrpcRequestInit) =>
	jsonGet<Blob_.$output>(ctx, "sh.tangled.repo.blob", asParams(params), init);

export const branch = (ctx: BobbinContext, params: Branch.$params, init?: XrpcRequestInit) =>
	jsonGet<Branch.$output>(ctx, "sh.tangled.repo.branch", asParams(params), init);

export const getDefaultBranch = (
	ctx: BobbinContext,
	params: GetDefaultBranch.$params,
	init?: XrpcRequestInit
) =>
	jsonGet<GetDefaultBranch.$output>(
		ctx,
		"sh.tangled.repo.getDefaultBranch",
		asParams(params),
		init
	);

export const describeRepo = (
	ctx: BobbinContext,
	params: DescribeRepo.$params,
	init?: XrpcRequestInit
) => jsonGet<DescribeRepo.$output>(ctx, "sh.tangled.repo.describeRepo", asParams(params), init);

export const languages = (ctx: BobbinContext, params: Languages.$params, init?: XrpcRequestInit) =>
	jsonGet<Languages.$output>(ctx, "sh.tangled.repo.languages", asParams(params), init);

export const listSecrets = (
	ctx: BobbinContext,
	params: ListSecrets.$params,
	init?: XrpcRequestInit
) => jsonGet<ListSecrets.$output>(ctx, "sh.tangled.repo.listSecrets", asParams(params), init);

// schema-less json passthroughs; callers supply the shape.

export const log = <T = unknown>(ctx: BobbinContext, params: Log.$params, init?: XrpcRequestInit) =>
	jsonGet<T>(ctx, "sh.tangled.repo.log", asParams(params), init);

export const diff = <T = unknown>(
	ctx: BobbinContext,
	params: Diff.$params,
	init?: XrpcRequestInit
) => jsonGet<T>(ctx, "sh.tangled.repo.diff", asParams(params), init);

export const compare = <T = unknown>(
	ctx: BobbinContext,
	params: Compare.$params,
	init?: XrpcRequestInit
) => jsonGet<T>(ctx, "sh.tangled.repo.compare", asParams(params), init);

export const branches = <T = unknown>(
	ctx: BobbinContext,
	params: Branches.$params,
	init?: XrpcRequestInit
) => jsonGet<T>(ctx, "sh.tangled.repo.branches", asParams(params), init);

export const tags = <T = unknown>(
	ctx: BobbinContext,
	params: Tags.$params,
	init?: XrpcRequestInit
) => jsonGet<T>(ctx, "sh.tangled.repo.tags", asParams(params), init);

export const tag = <T = unknown>(ctx: BobbinContext, params: Tag.$params, init?: XrpcRequestInit) =>
	jsonGet<T>(ctx, "sh.tangled.repo.tag", asParams(params), init);

// raw response for streaming/download.

export const archive = (ctx: BobbinContext, params: Archive.$params, init?: XrpcRequestInit) =>
	rawGet(ctx, "sh.tangled.repo.archive", asParams(params), init);

// the knot picks the content type and only serves images, video and text, so a
// reader can go straight here instead of us proxying it
export const blobRawUrl = (
	serviceUrl: string,
	// not `Blob_.$params`, the record wrappers hand back plain strings and
	// nothing here would satisfy the generated at-uri brand
	params: { repo: string; ref: string; path: string }
): string => buildUrl(serviceUrl, "sh.tangled.repo.blob", { ...params, raw: true }).toString();
