import { z } from 'zod';
import { type APIClient, APIResponseSchema } from '../api.ts';
import { MalwareCheckError } from './util.ts';

export const PackageRefSchema = z
	.object({
		name: z.string().describe('Package name (e.g., lodash, express).'),
		version: z.string().describe('Package version (e.g., 4.17.21).'),
	})
	.describe('Reference to an npm package with name and version.');

export type PackageRef = z.infer<typeof PackageRefSchema>;

export const MalwareFindingSchema = z
	.object({
		name: z.string().describe('Name of the flagged package.'),
		version: z.string().describe('Version of the flagged package.'),
		reason: z.string().describe('Reason why the package was flagged as potentially malicious.'),
	})
	.describe('A malware detection finding for a specific package.');

export type MalwareFinding = z.infer<typeof MalwareFindingSchema>;

export const MalwareCheckSummarySchema = z
	.object({
		scanned: z.number().describe('Total number of packages scanned.'),
		flagged: z.number().describe('Number of packages flagged as potentially malicious.'),
	})
	.describe('Summary of a malware check scan.');

export const MalwareCheckListMetadataSchema = z
	.object({
		fetchedAt: z.string().describe('ISO 8601 timestamp when the malware list was last fetched.'),
		count: z.number().describe('Number of entries in the malware list.'),
	})
	.describe('Metadata about the malware detection list used for scanning.');

export const MalwareCheckResultSchema = z
	.object({
		action: z
			.enum(['allow', 'block'])
			.describe('Action to take based on the scan results (allow or block deployment).'),
		summary: MalwareCheckSummarySchema.describe('Summary of the malware check scan.'),
		findings: z.array(MalwareFindingSchema).describe('List of malware detection findings.'),
		list: MalwareCheckListMetadataSchema.optional().describe(
			'Metadata about the malware list used, if available.'
		),
		error: z
			.string()
			.optional()
			.describe('Error message if the malware check encountered an issue.'),
	})
	.describe('Result of a malware check for a deployment.');

export const MalwareCheckResponseSchema = APIResponseSchema(MalwareCheckResultSchema);

export type MalwareCheckResult = z.infer<typeof MalwareCheckResultSchema>;

export async function projectDeploymentMalwareCheck(
	client: APIClient,
	deploymentId: string,
	packages: PackageRef[],
	signal?: AbortSignal
): Promise<MalwareCheckResult> {
	const resp = await client.request<z.infer<typeof MalwareCheckResponseSchema>>(
		'POST',
		`/security/${encodeURIComponent(deploymentId)}/malware-check`,
		MalwareCheckResponseSchema,
		{
			ecosystem: 'npm',
			packages,
		},
		undefined,
		signal
	);

	if (!resp.success) {
		throw new MalwareCheckError({
			message: resp.message || 'Malware check request failed',
			deploymentId,
		});
	}

	return resp.data;
}
