import type { NarratorContext, HeroType } from './useFetchNarratorText' interface NarratorMessage { context: NarratorContext priority: number } const HINT_COOLDOWN = 120000 const isVisible = ref(false) const currentMessage = ref('') const messageQueue = ref([]) const isProcessing = ref(false) const shownEncouragements = ref>(new Set()) const lastHintTime = ref(0) export function useNarrator() { const { fetchText } = useFetchNarratorText() const progressionStore = useProgressionStore() async function queueMessage(context: NarratorContext, priority: number = 5) { messageQueue.value.push({ context, priority }) messageQueue.value.sort((a, b) => b.priority - a.priority) if (!isProcessing.value) { processQueue() } } async function processQueue() { if (messageQueue.value.length === 0) { isProcessing.value = false return } isProcessing.value = true const next = messageQueue.value.shift()! try { const heroType = progressionStore.hero as HeroType | undefined const response = await fetchText(next.context, heroType ?? undefined) if (response) { currentMessage.value = response.text isVisible.value = true } else { processQueue() } } catch { processQueue() } } function hide() { isVisible.value = false setTimeout(() => { processQueue() }, 300) } async function showIntro() { if (progressionStore.hasExistingProgress) { await queueMessage('welcome_back', 10) } else { await queueMessage('intro', 10) } } async function showTransition(zone: 'projects' | 'skills' | 'testimonials' | 'journey') { const contextMap: Record = { projects: 'transition_projects', skills: 'transition_skills', testimonials: 'transition_testimonials', journey: 'transition_journey', } await queueMessage(contextMap[zone], 7) } async function showEncouragement(percent: number) { let context: NarratorContext | null = null if (percent >= 75 && !shownEncouragements.value.has(75)) { context = 'encouragement_75' shownEncouragements.value.add(75) } else if (percent >= 50 && !shownEncouragements.value.has(50)) { context = 'encouragement_50' shownEncouragements.value.add(50) } else if (percent >= 25 && !shownEncouragements.value.has(25)) { context = 'encouragement_25' shownEncouragements.value.add(25) } if (context) { await queueMessage(context, 5) } } async function showHint() { const now = Date.now() if (now - lastHintTime.value < HINT_COOLDOWN) return lastHintTime.value = now await queueMessage('hint', 3) } async function showContactUnlocked() { await queueMessage('contact_unlocked', 8) } return { isVisible: readonly(isVisible), currentMessage: readonly(currentMessage), hide, showIntro, showTransition, showEncouragement, showHint, showContactUnlocked, } }