// mirrors the helpers on types.Pipeline in types/pipeline.go

import type {
	PipelineStatus,
	PipelineSummary,
	PipelineTriggerKind
} from "$lib/components/repo/types";

/** the trigger tabs */
export type PipelineFilter = "all" | PipelineTriggerKind;

/** what search looks at. a real bobbin query has to cover the same fields. */
export const matchesQuery = (pipeline: PipelineSummary, query: string): boolean => {
	const needle = query.trim().toLowerCase();
	if (!needle) return true;

	const haystack = [
		pipeline.sha,
		pipeline.trigger.kind === "manual" ? "manual dispatch" : pipeline.trigger.targetRef,
		pipeline.trigger.kind === "pull_request" ? pipeline.trigger.sourceLabel : "",
		...pipeline.workflows.map((workflow) => workflow.name)
	];
	return haystack.some((field) => field.toLowerCase().includes(needle));
};

/** the order the breakdown lists statuses in */
export const STATUS_ORDER: PipelineStatus[] = [
	"success",
	"failed",
	"timeout",
	"cancelled",
	"running",
	"pending"
];

export const STATUS_LABELS: Record<PipelineStatus, string> = {
	pending: "Pending",
	running: "Running",
	success: "Passed",
	failed: "Failed",
	timeout: "Timed out",
	cancelled: "Cancelled"
};

export const statusCounts = (pipeline: PipelineSummary): Record<PipelineStatus, number> => {
	const counts = {
		pending: 0,
		running: 0,
		success: 0,
		failed: 0,
		timeout: 0,
		cancelled: 0
	};
	for (const workflow of pipeline.workflows) counts[workflow.status]++;
	return counts;
};

/** one status for the whole run. anything still going wins, so an in-flight run says so. */
export const aggregateStatus = (pipeline: PipelineSummary): PipelineStatus => {
	// no workflows yet means no spindle has picked it up
	if (pipeline.workflows.length === 0) return "pending";

	const counts = statusCounts(pipeline);
	if (counts.running > 0) return "running";
	if (counts.pending > 0) return "pending";
	if (counts.failed > 0) return "failed";
	if (counts.timeout > 0) return "timeout";
	if (counts.cancelled > 0) return "cancelled";
	return "success";
};

/** how many workflows are done — everything except pending and running */
export const finishedCount = (pipeline: PipelineSummary): number => {
	const counts = statusCounts(pipeline);
	return counts.success + counts.failed + counts.timeout + counts.cancelled;
};

/** "2/3 passed, 1/3 failed" */
export const longSummary = (pipeline: PipelineSummary): string => {
	const counts = statusCounts(pipeline);
	const total = pipeline.workflows.length;
	return STATUS_ORDER.filter((status) => counts[status] > 0)
		.map((status) => `${counts[status]}/${total} ${STATUS_LABELS[status].toLowerCase()}`)
		.join(", ");
};

/** sum of the workflows, not wall time across the run */
export const totalDuration = (pipeline: PipelineSummary): number =>
	pipeline.workflows.reduce((sum, workflow) => sum + workflow.duration, 0);
