<script lang="ts" setup>
import ActionsDropdownMenu from '@/app/components/MainHeader/ActionsDropdownMenu.vue';
import WorkflowHistoryButton from '@/features/workflows/workflowHistory/components/WorkflowHistoryButton.vue';
import type { FolderShortInfo } from '@/features/core/folders/folders.types';
import type { IWorkflowDb } from '@/Interface';
import type { PermissionsRecord } from '@n8n/permissions';
import { computed, onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';
import { WORKFLOW_PUBLISH_MODAL_KEY } from '@/app/constants';
import { N8nButton, N8nIcon, N8nTooltip } from '@n8n/design-system';
import { useI18n } from '@n8n/i18n';
import { useUIStore } from '@/app/stores/ui.store';
import { useWorkflowsStore } from '@/app/stores/workflows.store';
import SaveButton from '@/app/components/SaveButton.vue';
import TimeAgo from '@/app/components/TimeAgo.vue';
import { getActivatableTriggerNodes } from '@/app/utils/nodeTypesUtils';
import { useWorkflowSaving } from '@/app/composables/useWorkflowSaving';
import { useRouter } from 'vue-router';
import {
	getLastPublishedVersion,
	generateVersionName,
} from '@/features/workflows/workflowHistory/utils';
import { nodeViewEventBus } from '@/app/event-bus';
import CollaborationPane from '@/features/collaboration/collaboration/components/CollaborationPane.vue';

const props = defineProps<{
	readOnly?: boolean;
	id: IWorkflowDb['id'];
	tags: IWorkflowDb['tags'];
	name: IWorkflowDb['name'];
	meta: IWorkflowDb['meta'];
	currentFolder?: FolderShortInfo;
	isArchived: IWorkflowDb['isArchived'];
	isNewWorkflow: boolean;
	workflowPermissions: PermissionsRecord['workflow'];
}>();

defineEmits<{
	'workflow:saved': [];
}>();

const actionsMenuRef = useTemplateRef<InstanceType<typeof ActionsDropdownMenu>>('actionsMenu');
const locale = useI18n();
const uiStore = useUIStore();
const workflowsStore = useWorkflowsStore();
const i18n = useI18n();
const router = useRouter();
const { saveCurrentWorkflow } = useWorkflowSaving({ router });
// We're dropping the save button soon with the autosave so this will also be dropped
const autoSaveForPublish = ref(false);

const isWorkflowSaving = computed(() => {
	return uiStore.isActionActive.workflowSaving && !autoSaveForPublish.value;
});

const importFileRef = computed(() => actionsMenuRef.value?.importFileRef);

const onPublishButtonClick = async () => {
	// If there are unsaved changes, save the workflow first
	if (uiStore.stateIsDirty || props.isNewWorkflow) {
		autoSaveForPublish.value = true;
		const saved = await saveCurrentWorkflow({}, true);
		autoSaveForPublish.value = false;
		if (!saved) {
			// If save failed, don't open the modal
			return;
		}
	}

	uiStore.openModalWithData({
		name: WORKFLOW_PUBLISH_MODAL_KEY,
		data: {},
	});
};

const foundTriggers = computed(() =>
	getActivatableTriggerNodes(workflowsStore.workflowTriggerNodes),
);

const containsTrigger = computed((): boolean => {
	return foundTriggers.value.length > 0;
});

const isWorkflowSaved = computed(() => {
	return !uiStore.stateIsDirty && !props.isNewWorkflow;
});

const publishButtonEnabled = computed(() => {
	if (!props.workflowPermissions.publish) {
		return false;
	}

	if (!containsTrigger.value) {
		return false;
	}

	if (workflowsStore.nodesIssuesExist) {
		return false;
	}

	return (
		(workflowsStore.workflow.versionId &&
			workflowsStore.workflow.versionId !== workflowsStore.workflow.activeVersion?.versionId) ||
		uiStore.stateIsDirty
	);
});

const publishTooltipText = computed(() => {
	if (!props.workflowPermissions.publish) {
		return i18n.baseText('workflows.publish.permissionDenied');
	}

	const wfHasAnyChanges =
		workflowsStore.workflow.versionId !== workflowsStore.workflow.activeVersion?.versionId;

	if (!containsTrigger.value) {
		return i18n.baseText('workflows.publishModal.noTriggerMessage');
	}

	if (workflowsStore.nodesIssuesExist) {
		return i18n.baseText('workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.title', {
			interpolate: { count: workflowsStore.nodesWithIssues.length },
			adjustToNumber: workflowsStore.nodesWithIssues.length,
		});
	}

	if (!wfHasAnyChanges && !uiStore.stateIsDirty) {
		return i18n.baseText('workflows.publishModal.noChanges');
	}

	return '';
});

const activeVersion = computed(() => workflowsStore.workflow.activeVersion);

const activeVersionName = computed(() => {
	if (!activeVersion.value) {
		return '';
	}
	return activeVersion.value.name || generateVersionName(activeVersion.value.versionId);
});

const latestPublishDate = computed(() => {
	const latestPublish = getLastPublishedVersion(activeVersion.value?.workflowPublishHistory ?? []);
	return latestPublish?.createdAt;
});

onMounted(() => {
	nodeViewEventBus.on('publishWorkflow', onPublishButtonClick);
});

onBeforeUnmount(() => {
	nodeViewEventBus.off('publishWorkflow', onPublishButtonClick);
});

defineExpose({
	importFileRef,
});
</script>

<template>
	<div :class="$style.container">
		<CollaborationPane v-if="!isNewWorkflow" />
		<div
			v-if="activeVersion"
			:class="$style.activeVersionIndicator"
			data-test-id="workflow-active-version-indicator"
		>
			<N8nTooltip>
				<template #content>
					{{ activeVersionName }}<br />{{ i18n.baseText('workflowHistory.item.active') }}
					<TimeAgo v-if="latestPublishDate" :date="latestPublishDate" />
				</template>
				<N8nIcon icon="circle-check" color="success" size="xlarge" :class="$style.icon" />
			</N8nTooltip>
		</div>
		<div
			v-if="!isArchived && (workflowPermissions.update || workflowPermissions.publish)"
			:class="$style.publishButtonWrapper"
		>
			<N8nTooltip :disabled="!publishTooltipText">
				<template #content>
					{{ publishTooltipText }}
				</template>
				<N8nButton
					:loading="autoSaveForPublish"
					:disabled="!publishButtonEnabled || isWorkflowSaving"
					type="secondary"
					data-test-id="workflow-open-publish-modal-button"
					@click="onPublishButtonClick"
				>
					{{ locale.baseText('workflows.publish') }}
				</N8nButton>
			</N8nTooltip>
		</div>
		<SaveButton
			type="primary"
			:saved="isWorkflowSaved"
			:disabled="
				isWorkflowSaving ||
				readOnly ||
				isArchived ||
				(!isNewWorkflow && !workflowPermissions.update)
			"
			:is-saving="isWorkflowSaving"
			:with-shortcut="!readOnly && !isArchived && workflowPermissions.update"
			:shortcut-tooltip="i18n.baseText('saveWorkflowButton.hint')"
			data-test-id="workflow-save-button"
			@click="$emit('workflow:saved')"
		/>
		<WorkflowHistoryButton :workflow-id="props.id" :is-new-workflow="isNewWorkflow" />
		<ActionsDropdownMenu
			:id="id"
			ref="actionsMenu"
			:workflow-permissions="workflowPermissions"
			:is-new-workflow="isNewWorkflow"
			:read-only="readOnly"
			:is-archived="isArchived"
			:name="name"
			:tags="tags"
			:current-folder="currentFolder"
			:meta="meta"
			@workflow:saved="$emit('workflow:saved')"
		/>
	</div>
</template>

<style lang="scss" module>
.container {
	display: contents;
}

.activeVersionIndicator {
	display: inline-flex;
	align-items: center;

	.icon:focus {
		outline: none;
	}
}

.publishButtonWrapper {
	position: relative;
	display: inline-block;
}
</style>
