import { useCallback, useEffect, useMemo, useState } from 'react' import { useLazyCheckQueueStatusQuery, useSubmitSolutionMutation, } from '../__data__/api/api' import type { ChallengeSubmission, QueueStatus } from '../__data__/types' import { useChallenge } from '../context/ChallengeContext' import { loadFinalAnswer, saveFinalAnswer } from '../utils/drafts' interface UseSubmissionArgs { taskId: string } interface SubmissionResult { result: string setResult: (value: string) => void submit: () => Promise reset: () => void queueStatus: QueueStatus | null finalSubmission: ChallengeSubmission | null isSubmitting: boolean } export const useSubmission = ({ taskId }: UseSubmissionArgs): SubmissionResult => { const { userId, eventEmitter, pollingManager, behaviorTracker, metricsCollector, saveDraft, loadDraft, clearDraft, } = useChallenge() const [result, setResultState] = useState('') const [queueId, setQueueId] = useState(null) const [queueStatus, setQueueStatus] = useState(null) const [finalSubmission, setFinalSubmission] = useState(null) const [submitSolution, { isLoading: isSubmitting }] = useSubmitSolutionMutation() const [triggerCheckStatus] = useLazyCheckQueueStatusQuery() useEffect(() => { behaviorTracker.reset() // Сначала проверяем финальный ответ (если задание уже решалось) const finalAnswer = loadFinalAnswer(taskId) if (finalAnswer) { setResultState(finalAnswer) behaviorTracker.markDraftUsed() } else { // Если финального ответа нет, проверяем черновик const draft = loadDraft(taskId) if (draft) { setResultState(draft) behaviorTracker.markDraftUsed() } else { // Если ничего нет - пустое поле setResultState('') } } pollingManager.stop() setQueueId(null) setQueueStatus(null) setFinalSubmission(null) }, [behaviorTracker, loadDraft, pollingManager, taskId]) const setResult = useCallback( (value: string) => { setResultState(value) behaviorTracker.onTextChange(value) saveDraft(taskId, value) }, [behaviorTracker, saveDraft, taskId], ) const reset = useCallback(() => { setResultState('') setQueueId(null) setQueueStatus(null) setFinalSubmission(null) behaviorTracker.reset() pollingManager.stop() clearDraft(taskId) }, [behaviorTracker, clearDraft, pollingManager, taskId]) const submit = useCallback(async () => { if (!userId) { throw new Error('Пользователь не авторизован') } if (!result.trim()) { return } pollingManager.stop() setFinalSubmission(null) setQueueStatus(null) const { queueId: newQueueId } = await submitSolution({ userId, taskId, result }).unwrap() setQueueId(newQueueId) metricsCollector.startTracking(queueStatus?.position ?? 0) pollingManager.start(async () => { const status = await triggerCheckStatus(newQueueId, false).unwrap() metricsCollector.incrementPoll() setQueueStatus(status) if (status.status === 'completed' && status.submission) { const performanceMetrics = metricsCollector.getMetrics(status.submission) const behaviorMetrics = behaviorTracker.getMetrics(result) const eventPayload = { submission: status.submission, performanceMetrics, behaviorMetrics, } eventEmitter.emit({ type: 'submission_completed', timestamp: new Date().toISOString(), userId, data: eventPayload, }) setFinalSubmission(status.submission) // Сохраняем финальный ответ для восстановления при возврате saveFinalAnswer(taskId, result) // Очищаем черновик, так как теперь есть финальный ответ clearDraft(taskId) pollingManager.stop() return false } if (status.status === 'error') { pollingManager.stop() return false } return true }) }, [ behaviorTracker, clearDraft, eventEmitter, metricsCollector, pollingManager, queueStatus?.position, result, submitSolution, taskId, triggerCheckStatus, userId, ]) return useMemo( () => ({ result, setResult, submit, reset, queueStatus, finalSubmission, isSubmitting, }), [finalSubmission, isSubmitting, queueStatus, reset, result, setResult, submit], ) }