<script module lang="ts">
	import { tv, type VariantProps } from "tailwind-variants";
	import type { TagVariants } from "$lib/components/ui/Tag.svelte";
	import type { PipelineStatus } from "$lib/components/repo/types";

	export const pipelineCardContent = tv({
		slots: {
			// does not wrap: a long branch name wraps inside the trigger group instead, so the
			// sha stays pinned top-right
			header: "flex items-start justify-between gap-3 pb-2",
			trigger: "flex min-w-0 flex-wrap items-center gap-x-1.5 gap-y-1",
			triggerRow: "flex flex-wrap items-center gap-x-1.5 gap-y-1 text-foreground-default",
			triggerIcon: "size-4 shrink-0 text-foreground-muted",
			triggerVerb: "text-foreground-muted",
			triggerRef: "font-semibold",
			triggerArrow: "size-3 shrink-0 text-foreground-muted",
			pullLink: "typography-paragraph-small text-foreground-muted no-underline hover:underline",
			sha: "shrink-0 rounded-sm bg-background-inset px-2 py-0.5 typography-monospace-small text-foreground-default no-underline hover:underline",
			meta: "flex flex-wrap items-center justify-between text-foreground-muted",
			metaSub: "flex flex-wrap items-center gap-2",
			workflows: "ml-1",
			duration: "inline-flex items-center gap-1",
			durationIcon: "size-3 shrink-0"
		},
		variants: {
			// the trigger line is only a link once a workflow exists to open
			linked: {
				true: { triggerRow: "no-underline hover:underline" },
				false: {}
			}
		},
		defaultVariants: {
			linked: false
		}
	});

	export type PipelineCardContentVariants = VariantProps<typeof pipelineCardContent>;

	/** which Tag colour each status uses */
	export const STATUS_TAG_COLORS: Record<PipelineStatus, TagVariants["color"]> = {
		pending: "gray",
		running: "warning",
		success: "success",
		failed: "danger",
		timeout: "warning",
		cancelled: "gray"
	};
</script>

<script lang="ts">
	import { resolve } from "$app/paths";
	import ArrowLeft from "$icon/arrow-left";
	import CirclePlay from "$icon/circle-play";
	import Clock from "$icon/clock";
	import GitCommitHorizontal from "$icon/git-commit-horizontal";
	import GitPullRequest from "$icon/git-pull-request";
	import TimeAgo from "$lib/components/ui/TimeAgo.svelte";
	import { formatDuration } from "$lib/format";
	import Tag from "$lib/components/ui/Tag.svelte";
	import type { PipelineSummary } from "$lib/components/repo/types";
	import { aggregateStatus, longSummary, STATUS_LABELS, totalDuration } from "./pipeline";
	import { STATUS_ICONS } from "./PipelineStatusIcon.svelte";
	import PipelineWorkflows from "./PipelineWorkflows.svelte";
	import Separator from "$lib/components/ui/Separator.svelte";

	interface Props {
		ownerHandle: string;
		repoName: string;
		pipeline: PipelineSummary;
	}

	let { ownerHandle, repoName, pipeline }: Props = $props();

	const status = $derived(aggregateStatus(pipeline));
	const duration = $derived(totalDuration(pipeline));

	// links to the first workflow's logs, plain text until a spindle reports one
	// TODO: the workflow log route does not exist in the svelte app yet
	const href = $derived(
		pipeline.workflows.length > 0
			? resolve(
					`/${ownerHandle}/${repoName}/pipelines/${pipeline.id}/workflow/${pipeline.workflows[0].name}` as "/"
				)
			: undefined
	);
	const commitHref = $derived(resolve(`/${ownerHandle}/${repoName}/commit/${pipeline.sha}` as "/"));

	const classes = $derived(pipelineCardContent({ linked: href !== undefined }));
</script>

{#snippet triggerLabel()}
	{#if pipeline.trigger.kind === "push"}
		<GitCommitHorizontal class={classes.triggerIcon()} aria-hidden="true" />
		<span class={classes.triggerVerb()}>Push to</span>
		<span class={classes.triggerRef()}>{pipeline.trigger.targetRef}</span>
	{:else if pipeline.trigger.kind === "pull_request"}
		<GitPullRequest class={classes.triggerIcon()} aria-hidden="true" />
		<span class={classes.triggerVerb()}>Pull request</span>
		<span class={classes.triggerRef()}>{pipeline.trigger.targetRef}</span>
		<ArrowLeft class={classes.triggerArrow()} aria-hidden="true" />
		<span class={classes.triggerRef()}>{pipeline.trigger.sourceLabel}</span>
	{:else}
		<CirclePlay class={classes.triggerIcon()} aria-hidden="true" />
		<span class={classes.triggerVerb()}>Manual dispatch</span>
	{/if}
{/snippet}

<div class={classes.header()}>
	<div class={classes.trigger()}>
		{#if href}
			<a {href} class={classes.triggerRow()}>
				{@render triggerLabel()}
			</a>
		{:else}
			<span class={classes.triggerRow()}>
				{@render triggerLabel()}
			</span>
		{/if}

		{#if pipeline.trigger.kind === "pull_request" && pipeline.trigger.pullPath}
			<a href={resolve(pipeline.trigger.pullPath as "/")} class={classes.pullLink()}> (view PR) </a>
		{/if}
	</div>

	{#if pipeline.sha}
		<a href={commitHref} class={classes.sha()}>
			{pipeline.sha.slice(0, 8)}
		</a>
	{/if}
</div>

<div class={classes.meta()}>
	<span class={classes.metaSub()}>
		<Tag class="mt-px" size="lg" color={STATUS_TAG_COLORS[status]} icon={STATUS_ICONS[status]}
			>{STATUS_LABELS[status]}</Tag
		>

		<span class={classes.workflows()} title={longSummary(pipeline) || undefined}>
			<PipelineWorkflows {ownerHandle} {repoName} {pipeline} />
		</span>
	</span>

	<span class={classes.metaSub()}>
		<TimeAgo value={pipeline.createdAt} />

		{#if duration > 0}
			<Separator variant="dot" />
			<span class={classes.duration()}>
				<Clock class={classes.durationIcon()} aria-hidden="true" />
				{formatDuration(duration)}
			</span>
		{/if}
	</span>
</div>
