<script lang="ts" setup>
import { useBuilderStore } from '@/features/ai/assistant/builder.store';
import { useChatPanelStore } from '@/features/ai/assistant/chatPanel.store';
import { useAssistantStore } from '@/features/ai/assistant/assistant.store';
import { useSettingsStore } from '@/app/stores/settings.store';
import { useDebounce } from '@/app/composables/useDebounce';
import { ASK_AI_SLIDE_IN_DURATION_MS, ASK_AI_SLIDE_OUT_DURATION_MS } from '@/app/constants';
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import AskAssistantBuild from './Agent/AskAssistantBuild.vue';
import AskAssistantChat from './Chat/AskAssistantChat.vue';
import AskModeCoachmark from './AskModeCoachmark.vue';
import { useAskModeCoachmark } from '../composables/useAskModeCoachmark';

import { N8nResizeWrapper } from '@n8n/design-system';
import HubSwitcher from '@/features/ai/assistant/components/HubSwitcher.vue';
import { useRoute } from 'vue-router';
import { useWorkflowId } from '@/app/composables/useWorkflowId';

const builderStore = useBuilderStore();
const assistantStore = useAssistantStore();
const chatPanelStore = useChatPanelStore();
const settingsStore = useSettingsStore();
const route = useRoute();
const workflowId = useWorkflowId();

const {
	isBuildMode,
	isMergeAskBuildEnabled,
	canToggleModes,
	shouldShowCoachmark,
	onDismissCoachmark,
} = useAskModeCoachmark();

// Track when slide animation has completed to prevent coachmark from appearing off-screen
const slideAnimationComplete = ref(false);
const canShowCoachmark = computed(() => shouldShowCoachmark.value && slideAnimationComplete.value);

// Reset animation state when panel closes
watch(
	() => chatPanelStore.isOpen,
	(isOpen) => {
		if (!isOpen) {
			slideAnimationComplete.value = false;
		}
	},
);

const askAssistantBuildRef = ref<InstanceType<typeof AskAssistantBuild>>();
const askAssistantChatRef = ref<InstanceType<typeof AskAssistantChat>>();

const chatWidth = computed(() => chatPanelStore.width);
const slideInDuration = `${ASK_AI_SLIDE_IN_DURATION_MS}ms`;
const slideOutDuration = `${ASK_AI_SLIDE_OUT_DURATION_MS}ms`;

function onResize(data: { direction: string; x: number; width: number }) {
	chatPanelStore.updateWidth(data.width);
}

function onResizeDebounced(data: { direction: string; x: number; width: number }) {
	void useDebounce().callDebounced(onResize, { debounceTime: 10, trailing: true }, data);
}

async function toggleAssistantMode() {
	const wasOpen = chatPanelStore.isOpen;
	const switchingToBuild = !isBuildMode.value;
	const newMode = switchingToBuild ? 'builder' : 'assistant';

	if (wasOpen) {
		if (switchingToBuild) {
			// Load sessions before switching mode if builder has no messages
			if (builderStore.chatMessages.length === 0) {
				await builderStore.fetchBuilderCredits();
				await builderStore.loadSessions();
			}
		}

		// Now switch the mode - data is already loaded
		chatPanelStore.switchMode(newMode);
	} else {
		// Opening from closed state - use full open logic
		await chatPanelStore.open({ mode: newMode });
	}
}

function onClose() {
	chatPanelStore.close();
}

function onSlideEnterComplete() {
	slideAnimationComplete.value = true;
	if (isBuildMode.value) {
		askAssistantBuildRef.value?.focusInput();
	} else {
		askAssistantChatRef.value?.focusInput();
	}
}

const unsubscribeAssistantStore = assistantStore.$onAction(({ name }) => {
	// When assistant is opened from error or credentials help
	// switch from build mode to chat mode (unless merge is enabled, which keeps builder mode)
	if (['initErrorHelper', 'initCredHelp'].includes(name) && !isMergeAskBuildEnabled.value) {
		chatPanelStore.switchMode('assistant');
	}
});

const unsubscribeBuilderStore = builderStore.$onAction(({ name }) => {
	if (['sendChatMessage'].includes(name)) {
		chatPanelStore.switchMode('builder');
	}
});

watch(route, () => {
	if (
		!assistantStore.currentSessionId ||
		!assistantStore.currentSessionWorkflowId ||
		assistantStore.currentSessionWorkflowId === workflowId.value
	) {
		return;
	}
	assistantStore.resetAssistantChat(workflowId.value);
});

// Set default mode based on which flags are enabled
onMounted(() => {
	// If toggle is not available (only one mode enabled), lock to the appropriate mode
	if (!canToggleModes.value) {
		if (builderStore.isAIBuilderEnabled) {
			// Only builder is enabled, lock to builder mode
			chatPanelStore.switchMode('builder');
		} else if (settingsStore.isAiAssistantEnabled) {
			// Only assistant is enabled, lock to assistant mode
			chatPanelStore.switchMode('assistant');
		}
	}
});

onBeforeUnmount(() => {
	unsubscribeAssistantStore();
	unsubscribeBuilderStore();
});
</script>

<template>
	<Transition
		:enter-active-class="$style.slideEnterActive"
		:enter-from-class="$style.slideFrom"
		:leave-active-class="$style.slideLeaveActive"
		:leave-to-class="$style.slideFrom"
		@after-enter="onSlideEnterComplete"
	>
		<div
			v-show="chatPanelStore.isOpen"
			:class="$style.slideWrapper"
			:style="{ width: `${chatWidth}px` }"
		>
			<N8nResizeWrapper
				:supported-directions="['left']"
				:width="chatWidth"
				:min-width="chatPanelStore.MIN_CHAT_WIDTH"
				:max-width="chatPanelStore.MAX_CHAT_WIDTH"
				:class="$style.resizeWrapper"
				data-test-id="ask-assistant-sidebar"
				@resize="onResizeDebounced"
			>
				<div :style="{ width: `${chatWidth}px` }" :class="$style.wrapper">
					<div :class="$style.assistantContent">
						<AskAssistantBuild v-if="isBuildMode" ref="askAssistantBuildRef" @close="onClose">
							<template v-if="canToggleModes" #header>
								<HubSwitcher :is-build-mode="isBuildMode" @toggle="toggleAssistantMode" />
							</template>
						</AskAssistantBuild>
						<AskAssistantChat v-else ref="askAssistantChatRef" @close="onClose">
							<!-- Header switcher is only visible when both modes are available in current view -->
							<template v-if="canToggleModes" #header>
								<AskModeCoachmark :visible="canShowCoachmark" @dismiss="onDismissCoachmark">
									<HubSwitcher :is-build-mode="isBuildMode" @toggle="toggleAssistantMode" />
								</AskModeCoachmark>
							</template>
						</AskAssistantChat>
					</div>
				</div>
			</N8nResizeWrapper>
		</div>
	</Transition>
</template>

<style lang="scss" module>
.slideWrapper {
	overflow: hidden;
	height: 100%;
}

.slideEnterActive {
	transition: width v-bind(slideInDuration) ease-in-out;
}

.slideLeaveActive {
	transition: width v-bind(slideOutDuration) ease-in-out;
}

.slideFrom {
	width: 0 !important;
}

.resizeWrapper {
	z-index: var(--ask-assistant-chat--z);
}

.wrapper {
	height: 100%;
	display: flex;
	flex-direction: column;
}

.assistantContent {
	flex: 1;
	overflow: hidden;
}
</style>
