import { requireProjectPermission } from "../../../middleware/projectAccess.js";
import { openapiRegisterPutPatchRoutesForLegacy } from "../../../utils/openapiDualRoute.js";
import { speakeasyOffsetLimitPagination } from "../../../utils/speakeasy.js";
import { OpenAPIHono } from "@hono/zod-openapi";
import { CredentialReferenceApiInsertSchema, CredentialReferenceApiSelectSchema, CredentialReferenceApiUpdateSchema, CredentialReferenceListResponse, CredentialReferenceResponse, ErrorResponseSchema, ListResponseSchema, PaginationQueryParamsSchema, TenantProjectIdParamsSchema, TenantProjectParamsSchema, commonGetErrorResponses, createApiError, createCredentialReference, deleteCredentialReference, getCredentialReferenceById, getCredentialReferenceWithResources, getCredentialStoreLookupKeyFromRetrievalParams, getUserScopedCredentialReference, listCredentialReferencesPaginated, updateCredentialReference, upsertCredentialReference } from "@inkeep/agents-core";
import { createProtectedRoute } from "@inkeep/agents-core/middleware";

//#region src/domains/manage/routes/credentials.ts
const app = new OpenAPIHono();
app.openapi(createProtectedRoute({
	method: "get",
	path: "/",
	summary: "List Credentials",
	operationId: "list-credentials",
	tags: ["Credentials"],
	permission: requireProjectPermission("view"),
	request: {
		params: TenantProjectParamsSchema,
		query: PaginationQueryParamsSchema
	},
	responses: {
		200: {
			description: "List of credentials retrieved successfully",
			content: { "application/json": { schema: CredentialReferenceListResponse } }
		},
		...commonGetErrorResponses
	},
	...speakeasyOffsetLimitPagination
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId } = c.req.valid("param");
	const page = Number(c.req.query("page")) || 1;
	const limit = Math.min(Number(c.req.query("limit")) || 10, 100);
	const result = await listCredentialReferencesPaginated(db)({
		scopes: {
			tenantId,
			projectId
		},
		pagination: {
			page,
			limit
		}
	});
	const validatedResult = ListResponseSchema(CredentialReferenceApiSelectSchema).parse(result);
	return c.json(validatedResult);
});
app.openapi(createProtectedRoute({
	method: "get",
	path: "/{id}",
	summary: "Get Credential",
	operationId: "get-credential-by-id",
	tags: ["Credentials"],
	permission: requireProjectPermission("view"),
	request: { params: TenantProjectIdParamsSchema },
	responses: {
		200: {
			description: "Credential found",
			content: { "application/json": { schema: CredentialReferenceResponse } }
		},
		...commonGetErrorResponses
	}
}), async (c) => {
	const { tenantId, projectId, id } = c.req.valid("param");
	const credential = await getCredentialReferenceWithResources(c.get("db"))({
		scopes: {
			tenantId,
			projectId
		},
		id
	});
	if (!credential) throw createApiError({
		code: "not_found",
		message: "Credential not found"
	});
	const validatedCredential = CredentialReferenceApiSelectSchema.parse(credential);
	return c.json({ data: validatedCredential });
});
app.openapi(createProtectedRoute({
	method: "post",
	path: "/",
	summary: "Create Credential",
	operationId: "create-credential",
	tags: ["Credentials"],
	permission: requireProjectPermission("edit"),
	request: {
		params: TenantProjectParamsSchema,
		body: { content: { "application/json": { schema: CredentialReferenceApiInsertSchema } } }
	},
	responses: {
		200: {
			description: "Credential updated successfully (user-scoped upsert)",
			content: { "application/json": { schema: CredentialReferenceResponse } }
		},
		201: {
			description: "Credential created successfully",
			content: { "application/json": { schema: CredentialReferenceResponse } }
		},
		...commonGetErrorResponses
	}
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId } = c.req.valid("param");
	const credentialData = {
		...c.req.valid("json"),
		tenantId,
		projectId
	};
	let oldLookupKey;
	let oldStore;
	const isUserScoped = !!(credentialData.toolId && credentialData.userId);
	let hadExistingUserScopedCredential = false;
	if (isUserScoped) {
		const existingCredential = await getUserScopedCredentialReference(db)({
			scopes: {
				tenantId,
				projectId
			},
			toolId: credentialData.toolId,
			userId: credentialData.userId
		});
		hadExistingUserScopedCredential = existingCredential != null;
		if (existingCredential?.retrievalParams) {
			oldStore = c.get("credentialStores").get(existingCredential.credentialStoreId);
			if (oldStore) oldLookupKey = getCredentialStoreLookupKeyFromRetrievalParams({
				retrievalParams: existingCredential.retrievalParams,
				credentialStoreType: oldStore.type
			});
		}
	}
	const credential = isUserScoped ? await upsertCredentialReference(db)({ data: credentialData }) : await createCredentialReference(db)(credentialData);
	if (oldLookupKey && oldStore) try {
		await oldStore.delete(oldLookupKey);
	} catch {}
	const validatedCredential = CredentialReferenceApiSelectSchema.parse(credential);
	const status = isUserScoped && hadExistingUserScopedCredential ? 200 : 201;
	return c.json({ data: validatedCredential }, status);
});
const updateCredentialRouteConfig = {
	path: "/{id}",
	summary: "Update Credential",
	tags: ["Credentials"],
	permission: requireProjectPermission("edit"),
	request: {
		params: TenantProjectIdParamsSchema,
		body: { content: { "application/json": { schema: CredentialReferenceApiUpdateSchema } } }
	},
	responses: {
		200: {
			description: "Credential updated successfully",
			content: { "application/json": { schema: CredentialReferenceResponse } }
		},
		...commonGetErrorResponses
	}
};
const updateCredentialHandler = async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, id } = c.req.valid("param");
	const body = c.req.valid("json");
	const updatedCredential = await updateCredentialReference(db)({
		scopes: {
			tenantId,
			projectId
		},
		id,
		data: body
	});
	if (!updatedCredential) throw createApiError({
		code: "not_found",
		message: "Credential not found"
	});
	const validatedCredential = CredentialReferenceApiSelectSchema.parse(updatedCredential);
	return c.json({ data: validatedCredential });
};
openapiRegisterPutPatchRoutesForLegacy(app, updateCredentialRouteConfig, updateCredentialHandler, { operationId: "update-credential" });
app.openapi(createProtectedRoute({
	method: "delete",
	path: "/{id}",
	summary: "Delete Credential",
	operationId: "delete-credential",
	tags: ["Credentials"],
	permission: requireProjectPermission("edit"),
	request: { params: TenantProjectIdParamsSchema },
	responses: {
		204: { description: "Credential deleted successfully" },
		404: {
			description: "Credential not found",
			content: { "application/json": { schema: ErrorResponseSchema } }
		}
	}
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, id } = c.req.valid("param");
	const credential = await getCredentialReferenceById(db)({
		scopes: {
			tenantId,
			projectId
		},
		id
	});
	if (!credential) throw createApiError({
		code: "not_found",
		message: "Credential not found"
	});
	const credentialStore = c.get("credentialStores").get(credential.credentialStoreId);
	if (credentialStore && credential.retrievalParams) {
		const lookupKey = getCredentialStoreLookupKeyFromRetrievalParams({
			retrievalParams: credential.retrievalParams,
			credentialStoreType: credentialStore.type
		});
		if (!lookupKey) throw createApiError({
			code: "bad_request",
			message: "Could not generate lookup key for credential store"
		});
		try {
			await credentialStore.delete(lookupKey);
		} catch (error) {
			console.error(`Failed to delete credential from external store "${credential.credentialStoreId}":`, error);
		}
	}
	if (!await deleteCredentialReference(db)({
		scopes: {
			tenantId,
			projectId
		},
		id
	})) throw createApiError({
		code: "not_found",
		message: "Failed to delete credential"
	});
	return c.body(null, 204);
});
var credentials_default = app;

//#endregion
export { credentials_default as default };