<script setup lang="ts">
import { saveAs } from 'file-saver';
import { useWorkflowsStore } from '@/app/stores/workflows.store';
import { useUIStore } from '@/app/stores/ui.store';
import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/app/constants/modals';
import { ViewableMimeTypes } from '@n8n/api-types';
import { useI18n } from '@n8n/i18n';
import type { IBinaryKeyData } from 'n8n-workflow';
import { BINARY_MODE_COMBINED } from 'n8n-workflow';
import { N8nButton, N8nLink, N8nNotice, N8nText } from '@n8n/design-system';
import { computed } from 'vue';
const { binaryData } = defineProps<{ binaryData: IBinaryKeyData[] }>();
import { usePostHog } from '@/app/stores/posthog.store';
import { EXECUTION_LOGIC_V2_EXPERIMENT } from '@/app/constants/experiments';

const emit = defineEmits<{ preview: [index: number, key: string | number] }>();

const i18n = useI18n();
const workflowsStore = useWorkflowsStore();
const uiStore = useUIStore();
const posthogStore = usePostHog();

const isV2Enabled = computed(() => {
	return posthogStore.isVariantEnabled(
		EXECUTION_LOGIC_V2_EXPERIMENT.name,
		EXECUTION_LOGIC_V2_EXPERIMENT.variant,
	);
});

const isLegacyBinaryMode = computed(
	() => workflowsStore.workflow.settings?.binaryMode !== BINARY_MODE_COMBINED,
);

function isViewable(index: number, key: string | number): boolean {
	const { mimeType } = binaryData[index][key];
	return ViewableMimeTypes.includes(mimeType);
}

function isDownloadable(index: number, key: string | number): boolean {
	const { mimeType, fileName } = binaryData[index][key];
	return !!(mimeType && fileName);
}

async function downloadBinaryData(index: number, key: string | number) {
	const { id, data, fileName, fileExtension, mimeType } = binaryData[index][key];

	if (id) {
		const url = workflowsStore.getBinaryUrl(id, 'download', fileName ?? '', mimeType);
		saveAs(url, [fileName, fileExtension].join('.'));
		return;
	} else {
		const bufferString = 'data:' + mimeType + ';base64,' + data;
		const blob = await fetch(bufferString).then(async (d) => await d.blob());
		saveAs(blob, fileName);
	}
}

function openWorkflowSettings() {
	uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
}
</script>

<template>
	<div :class="$style.component">
		<N8nNotice v-if="isLegacyBinaryMode && isV2Enabled" :class="$style.info" theme="info">
			{{ i18n.baseText('runData.legacyBinaryMode') }}
			<N8nLink size="small" @click="openWorkflowSettings">settings</N8nLink>.
		</N8nNotice>
		<N8nText v-if="binaryData.length === 0" align="center" tag="div">
			{{ i18n.baseText('runData.noBinaryDataFound') }}
		</N8nText>
		<div v-for="(binaryDataEntry, index) in binaryData" :key="index">
			<div v-if="binaryData.length > 1" :class="$style.binaryIndex">
				<div>
					{{ index + 1 }}
				</div>
			</div>

			<div :class="$style.binaryRow">
				<div
					v-for="(data, key) in binaryDataEntry"
					:key="index + '_' + key"
					:class="$style.binaryCell"
				>
					<div :data-test-id="'ndv-binary-data_' + index">
						<div :class="$style.binaryHeader">
							{{ key }}
						</div>
						<div v-if="data.fileName">
							<div>
								<N8nText size="small" :bold="true"
									>{{ i18n.baseText('runData.fileName') }}:
								</N8nText>
							</div>
							<div :class="$style.binaryValue">{{ data.fileName }}</div>
						</div>
						<div v-if="data.directory">
							<div>
								<N8nText size="small" :bold="true"
									>{{
										data.directory.startsWith('http://') || data.directory.startsWith('https://')
											? i18n.baseText('runData.url')
											: i18n.baseText('runData.directory')
									}}:
								</N8nText>
							</div>
							<div :class="$style.binaryValue">{{ data.directory }}</div>
						</div>
						<div v-if="data.fileExtension">
							<div>
								<N8nText size="small" :bold="true">
									{{ i18n.baseText('runData.fileExtension') }}:
								</N8nText>
							</div>
							<div :class="$style.binaryValue">{{ data.fileExtension }}</div>
						</div>
						<div v-if="data.mimeType">
							<div>
								<N8nText size="small" :bold="true">
									{{ i18n.baseText('runData.mimeType') }}:
								</N8nText>
							</div>
							<div :class="$style.binaryValue">{{ data.mimeType }}</div>
						</div>
						<div v-if="data.fileSize">
							<div>
								<N8nText size="small" :bold="true">
									{{ i18n.baseText('runData.fileSize') }}:
								</N8nText>
							</div>
							<div :class="$style.binaryValue">{{ data.fileSize }}</div>
						</div>

						<div :class="$style.binaryButtonContainer">
							<N8nButton
								v-if="isViewable(index, key)"
								size="small"
								:label="i18n.baseText('runData.showBinaryData')"
								data-test-id="ndv-view-binary-data"
								@click="emit('preview', index, key)"
							/>
							<N8nButton
								v-if="isDownloadable(index, key)"
								size="small"
								type="secondary"
								:label="i18n.baseText('runData.downloadBinaryData')"
								data-test-id="ndv-download-binary-data"
								@click="downloadBinaryData(index, key)"
							/>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<style lang="scss" module>
.component {
	position: absolute;
	top: 0;
	left: 0;
	padding: 0 var(--ndv--spacing) var(--spacing--3xl) var(--ndv--spacing);
	right: 0;
	overflow-y: auto;
	line-height: var(--line-height--xl);
	word-break: normal;
	height: 100%;
}

.binaryIndex {
	display: block;
	padding: var(--spacing--2xs);
	font-size: var(--font-size--2xs);

	> * {
		display: inline-block;
		width: 30px;
		height: 30px;
		line-height: 30px;
		border-radius: var(--radius);
		text-align: center;
		background-color: var(--color--foreground--shade-2);
		font-weight: var(--font-weight--bold);
		color: var(--color--text--tint-3);
	}
}

.binaryRow {
	display: inline-flex;
	font-size: var(--font-size--2xs);
}

.binaryCell {
	display: inline-block;
	width: 300px;
	overflow: hidden;
	background-color: var(--color--foreground--tint-2);
	margin-right: var(--ndv--spacing);
	margin-bottom: var(--ndv--spacing);
	border-radius: var(--radius);
	border: var(--border);
	padding: var(--ndv--spacing);
}

.binaryHeader {
	color: $color-primary;
	font-weight: var(--font-weight--bold);
	font-size: 1.2em;
	padding-bottom: var(--spacing--2xs);
	margin-bottom: var(--spacing--2xs);
	border-bottom: 1px solid var(--color--text--tint-1);
}

.binaryButtonContainer {
	margin-top: 1.5em;
	display: flex;
	flex-direction: row;
	justify-content: center;

	> * {
		flex-grow: 0;
		margin-right: var(--spacing--3xs);
	}
}

.binaryValue {
	white-space: initial;
	word-wrap: break-word;
}

.info {
	margin: var(--spacing--2xs) 0;
}
</style>
