import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Button, Card, Checkbox, Form, Input, Radio, Result, Select, Skeleton, Space, Tag, Typography, Upload, message, Progress } from 'antd';
import { LoadingOutlined, PlusOutlined, ThunderboltOutlined, InboxOutlined } from '@ant-design/icons';
import AiWorkingIllustration from '../../assets/ai-working.svg';
import type { UploadFile } from 'antd/es/upload/interface';

const { Paragraph, Title, Text } = Typography;
const { TextArea } = Input;
const { Dragger } = Upload;
const { Option } = Select;

interface WizardQuestion {
  order: number;
  name: string;
  label: string;
  control: string;
  input_type: string;
  required: boolean;
  priority?: number;
  rationale?: string;
  ask_if?: {
    field: string;
    op: '==' | '!=' | '>' | '<' | '>=' | '<=';
    value: any;
  } | null;
  options?: { label: string; value: string }[];
}

interface WizardDocument {
  id: string;
  name: string;
  required: boolean;
  priority?: number;
  hints?: string;
  accept?: string[];
}

interface FileBlock {
  id: string;
  fieldName: string;
  description: string;
  category?: string;
  files: UploadFile[];
  required?: boolean;
  docLabel?: string;
}

interface Props {
  formData: any;
  updateFormData: (data: any) => void;
  onNext: () => void;
  onPrev: () => void;
  addDebugEvent?: (type: string, status: string, message: string, data?: any) => void;
}

const evaluateCondition = (condition: WizardQuestion['ask_if'], values: Record<string, any>) => {
  if (!condition) return true;
  const left = values?.[condition.field];
  const right = condition.value;
  
  // Приводим к строкам для более надёжного сравнения (Radio.Group может возвращать строки)
  const leftStr = left != null ? String(left) : null;
  const rightStr = right != null ? String(right) : null;
  
  switch (condition.op) {
    case '==':
      return leftStr === rightStr;
    case '!=':
      return leftStr !== rightStr;
    case '>':
      return left > right;
    case '<':
      return left < right;
    case '>=':
      return left >= right;
    case '<=':
      return left <= right;
    default:
      return true;
  }
};

const buildPrefillMap = (prefill?: Array<{ name: string; value: any }>) => {
  if (!prefill || prefill.length === 0) return {};
  return prefill.reduce<Record<string, any>>((acc, item) => {
    if (item.name) {
      acc[item.name] = item.value;
    }
    return acc;
  }, {});
};

const YES_VALUES = ['да', 'yes', 'true', '1'];

const isAffirmative = (value: any) => {
  if (typeof value === 'boolean') {
    return value;
  }
  if (typeof value === 'string') {
    return YES_VALUES.includes(value.toLowerCase());
  }
  return false;
};

const generateBlockId = (prefix: string) =>
  `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;

export default function StepWizardPlan({
  formData,
  updateFormData,
  onNext,
  onPrev,
  addDebugEvent,
}: Props) {
  console.log('🔥 StepWizardPlan v1.4 - 2025-11-20 15:00 - Add unified_id and claim_id to wizard payload');
  const [form] = Form.useForm();
  const eventSourceRef = useRef<EventSource | null>(null);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
  const debugLoggerRef = useRef<typeof addDebugEvent>(addDebugEvent);
  const [isWaiting, setIsWaiting] = useState(!formData.wizardPlan);
  const [connectionError, setConnectionError] = useState<string | null>(null);
  const [plan, setPlan] = useState<any>(formData.wizardPlan || null);
  const [prefillMap, setPrefillMap] = useState<Record<string, any>>(
    formData.wizardPrefill || buildPrefillMap(formData.wizardPrefillArray)
  );
  const [questionFileBlocks, setQuestionFileBlocks] = useState<Record<string, FileBlock[]>>(
    formData.wizardUploads?.documents || {}
  );
  const [customFileBlocks, setCustomFileBlocks] = useState<FileBlock[]>(
    formData.wizardUploads?.custom || []
  );
  const [skippedDocuments, setSkippedDocuments] = useState<Set<string>>(
    new Set(formData.wizardSkippedDocuments || [])
  );
  const [submitting, setSubmitting] = useState(false);
  const [progressState, setProgressState] = useState<{ done: number; total: number }>({
    done: 0,
    total: 0,
  });
  const formValues = Form.useWatch([], form);
  const progressPercent = useMemo(() => {
    if (!progressState.total) return 0;
    return Math.round((progressState.done / progressState.total) * 100);
  }, [progressState]);

  useEffect(() => {
    debugLoggerRef.current = addDebugEvent;
  }, [addDebugEvent]);

  // ✅ Автосохранение прогресса заполнения (debounce 3 секунды)
  useEffect(() => {
    if (!formData.claim_id || !formValues) return;

    const timeoutId = setTimeout(() => {
      const answers = form.getFieldsValue(true);
      
      // Сохраняем только если есть хоть какие-то ответы
      const hasAnswers = Object.keys(answers).some(key => answers[key] !== undefined && answers[key] !== '');
      
      if (hasAnswers) {
        console.log('💾 Автосохранение прогресса:', { claim_id: formData.claim_id, answersCount: Object.keys(answers).length });
        
        // Обновляем formData с текущими ответами
        updateFormData({
          wizardAnswers: answers,
          wizardUploads: {
            documents: questionFileBlocks,
            custom: customFileBlocks,
          },
          wizardSkippedDocuments: Array.from(skippedDocuments),
        });
        
        addDebugEvent?.('wizard', 'info', '💾 Автосохранение прогресса');
      }
    }, 3000); // 3 секунды debounce

    return () => clearTimeout(timeoutId);
  }, [formValues, formData.claim_id]); // Зависимость от formValues, но БЕЗ questionFileBlocks/customFileBlocks/skippedDocuments (они обновляются отдельно)

  const questions: WizardQuestion[] = useMemo(() => plan?.questions || [], [plan]);
  const documents: WizardDocument[] = plan?.documents || [];

  const documentGroups = useMemo(() => {
    const groups: Record<string, WizardDocument[]> = {};
    documents.forEach((doc) => {
      const id = doc.id?.toLowerCase() || '';
      let key = 'docs_exist';
      if (id.includes('correspondence') || id.includes('chat')) {
        key = 'correspondence_exist';
      }
      if (!groups[key]) {
        groups[key] = [];
      }
      groups[key].push(doc);
    });
    return groups;
  }, [documents]);

  const documentCategoryOptions = useMemo(() => {
    const map = new Map<string, string>();
    documents.forEach((doc) => {
      const key = doc.id || doc.name || '';
      const label = doc.name || doc.id || '';
      if (key) {
        map.set(key, label);
      }
    });
    map.set('other', 'Другое');
    return Array.from(map.entries()).map(([value, label]) => ({ value, label }));
  }, [documents]);
  const customCategoryOptions = useMemo(() => documentCategoryOptions, [documentCategoryOptions]);

  const handleDocumentBlocksChange = useCallback(
    (docId: string, updater: (blocks: FileBlock[]) => FileBlock[]) => {
      setQuestionFileBlocks((prev) => {
        const nextDocs = { ...prev };
        const currentBlocks = nextDocs[docId] || [];
        const updated = updater(currentBlocks);
        nextDocs[docId] = updated;
        return nextDocs;
      });
    },
    []
  );

  const handleCustomBlocksChange = useCallback(
    (updater: (blocks: FileBlock[]) => FileBlock[]) => {
      setCustomFileBlocks((prev) => {
        const updated = updater(prev);
        return updated;
      });
    },
    []
  );

  const addDocumentBlock = (docId: string, docLabel?: string, docList?: WizardDocument[]) => {
    // Для предопределённых документов используем их ID как категорию
    const category = docList && docList.length === 1 && docList[0].id && !docList[0].id.includes('_exist')
      ? docList[0].id
      : docId;
    
    handleDocumentBlocksChange(docId, (blocks) => {
      // ✅ Автогенерация уникального описания:
      // - Первый блок: пустое (будет использоваться docLabel)
      // - Второй и далее: "docLabel #N"
      const blockNumber = blocks.length + 1;
      const autoDescription = blockNumber > 1 
        ? `${docLabel || docId} #${blockNumber}` 
        : '';
      
      return [
      ...blocks,
      {
        id: generateBlockId(docId),
        fieldName: docId,
          description: autoDescription,
          category: category,
        docLabel: docLabel,
        files: [],
      },
      ];
    });
  };

  const updateDocumentBlock = (
    docId: string,
    blockId: string,
    patch: Partial<Omit<FileBlock, 'id' | 'fieldName'>>
  ) => {
    handleDocumentBlocksChange(docId, (blocks) =>
      blocks.map((block) => (block.id === blockId ? { ...block, ...patch } : block))
    );
  };

  const removeDocumentBlock = (docId: string, blockId: string) => {
    handleDocumentBlocksChange(docId, (blocks) => blocks.filter((block) => block.id !== blockId));
  };

  const addCustomBlock = () => {
    handleCustomBlocksChange((blocks) => [
      ...blocks,
      {
        id: generateBlockId('custom'),
        fieldName: 'custom',
        description: '',
        category: undefined,
        files: [],
      },
    ]);
  };

  const updateCustomBlock = (blockId: string, patch: Partial<FileBlock>) => {
    handleCustomBlocksChange((blocks) =>
      blocks.map((block) => (block.id === blockId ? { ...block, ...patch } : block))
    );
  };

  const removeCustomBlock = (blockId: string) => {
    handleCustomBlocksChange((blocks) => blocks.filter((block) => block.id !== blockId));
  };

  useEffect(() => {
    if (plan) {
      const existingAnswers = formData.wizardAnswers || {};
      const initialValues = { ...prefillMap, ...existingAnswers };
      form.setFieldsValue(initialValues);
    }
  }, [plan, prefillMap, formData.wizardAnswers, form]);

  useEffect(() => {
    if (!questions.length) {
      setProgressState({ done: 0, total: 0 });
      return;
    }
    const values = formValues || {};
    let total = 0;
    let done = 0;

    questions.forEach((question) => {
      const visible = evaluateCondition(question.ask_if, values);
      if (question.required && visible) {
        total += 1;
        const value = values?.[question.name];
        let filled = false;
        if (Array.isArray(value)) {
          filled = value.length > 0;
        } else if (typeof value === 'boolean') {
          filled = value;
        } else {
          filled = value !== undefined && value !== null && String(value).trim().length > 0;
        }
        if (filled) {
          done += 1;
        }
      }
    });

    setProgressState({ done, total });
  }, [formValues, questions]);

  // Автоматически создаём блоки для ВСЕХ документов из плана при загрузке
  // Используем ref чтобы отслеживать какие блоки уже созданы
  const createdDocBlocksRef = useRef<Set<string>>(new Set());

  useEffect(() => {
    if (!plan || !documents || documents.length === 0) return;
    
    documents.forEach((doc) => {
      const docKey = doc.id || doc.name || `doc_unknown`;
      
      // Не создаём блок, если уже создавали
      if (createdDocBlocksRef.current.has(docKey)) return;
      
      // Не создаём блок, если документ пропущен
      if (skippedDocuments.has(docKey)) return;
      
      // Помечаем как созданный
      createdDocBlocksRef.current.add(docKey);
      
      const category = doc.id && !doc.id.includes('_exist') ? doc.id : docKey;
      handleDocumentBlocksChange(docKey, (blocks) => {
        // Проверяем ещё раз внутри callback
        if (blocks.length > 0) return blocks;
        return [
          ...blocks,
          {
            id: generateBlockId(docKey),
            fieldName: docKey,
            description: '',
            category: category,
            docLabel: doc.name,
            files: [],
          },
        ];
      });
    });
  }, [plan, documents, handleDocumentBlocksChange, skippedDocuments]);

  useEffect(() => {
    if (!isWaiting || !formData.session_id || plan) {
      console.log('⏭️ StepWizardPlan: пропускаем подписку SSE', {
        isWaiting,
        hasSessionId: !!formData.session_id,
        hasPlan: !!plan,
      });
      return;
    }

    const sessionId = formData.session_id;
    console.log('🔌 StepWizardPlan: подписываемся на SSE канал для получения wizard_plan', {
      session_id: sessionId,
      sse_url: `/events/${sessionId}`,
      redis_channel: `ocr_events:${sessionId}`,
    });
    
    const source = new EventSource(`/events/${sessionId}`);
    eventSourceRef.current = source;
    debugLoggerRef.current?.('wizard', 'info', '🔌 Подключаемся к SSE для плана вопросов', { session_id: sessionId });
    
    // Таймаут: если план не пришёл за 2 минуты (RAG может работать долго), показываем ошибку
    timeoutRef.current = setTimeout(() => {
      setConnectionError('План вопросов не получен. Проверьте, что n8n обработал описание проблемы.');
      debugLoggerRef.current?.('wizard', 'error', '⏱️ Таймаут ожидания плана вопросов (2 минуты)', { session_id: sessionId });
      if (eventSourceRef.current) {
        eventSourceRef.current.close();
        eventSourceRef.current = null;
      }
    }, 120000); // 2 минуты для RAG обработки

    source.onopen = () => {
      setConnectionError(null);
      debugLoggerRef.current?.('wizard', 'info', '✅ SSE соединение открыто', { session_id: sessionId });
    };

    source.onerror = (error) => {
      console.error('❌ Wizard SSE error:', error);
      setConnectionError('Не удалось получить ответ от AI. Попробуйте ещё раз.');
      source.close();
      eventSourceRef.current = null;
      debugLoggerRef.current?.('wizard', 'error', '❌ SSE ошибка (wizard)', { session_id: sessionId });
    };

    const extractWizardPayload = (incoming: any): any => {
      if (!incoming || typeof incoming !== 'object') return null;
      if (incoming.wizard_plan) return incoming;

      const candidates = [
        incoming.data,
        incoming.redis_value,
        incoming.event,
        incoming.payload,
      ];

      for (const candidate of candidates) {
        if (!candidate) continue;
        const unwrapped = extractWizardPayload(candidate);
        if (unwrapped) return unwrapped;
      }

      return null;
    };

    source.onmessage = (event) => {
      try {
        const payload = JSON.parse(event.data);
        const eventType =
          payload.event_type ||
          payload.type ||
          payload?.event?.event_type ||
          payload?.data?.event_type ||
          payload?.redis_value?.event_type;

        // Логируем все события для отладки
        debugLoggerRef.current?.('wizard', 'info', '📨 Получено SSE событие', {
          session_id: sessionId,
          event_type: eventType,
          has_wizard_plan: Boolean(extractWizardPayload(payload)),
          payload_keys: Object.keys(payload),
          payload_preview: JSON.stringify(payload).substring(0, 200),
        });

        // ✅ НОВЫЙ ФЛОУ: Обработка списка документов
        if (eventType === 'documents_list_ready') {
          const documentsRequired = payload.documents_required || [];
          
          debugLoggerRef.current?.('wizard', 'success', '📋 Получен список документов!', {
            session_id: sessionId,
            documents_count: documentsRequired.length,
            documents: documentsRequired.map((d: any) => d.name),
          });
          
          console.log('📋 documents_list_ready:', {
            claim_id: payload.claim_id,
            documents_required: documentsRequired,
          });
          
          // Сохраняем в formData для нового флоу
          updateFormData({
            documents_required: documentsRequired,
            claim_id: payload.claim_id,
            wizardPlanStatus: 'documents_ready',  // Новый статус
          });
          
          setIsWaiting(false);
          setConnectionError(null);
          
          if (timeoutRef.current) {
            clearTimeout(timeoutRef.current);
            timeoutRef.current = null;
          }
          
          // Пока показываем alert для теста, потом переход к StepDocumentsNew
          message.success(`Получен список документов: ${documentsRequired.length} шт.`);
          
          // TODO: onNext() для перехода к StepDocumentsNew
          return;
        }

        const wizardPayload = extractWizardPayload(payload);
        const hasWizardPlan = Boolean(wizardPayload);

        if (eventType?.includes('wizard') || hasWizardPlan) {
          const wizardPlan = wizardPayload?.wizard_plan;
          const answersPrefill = wizardPayload?.answers_prefill;
          const coverageReport = wizardPayload?.coverage_report;

          debugLoggerRef.current?.('wizard', 'success', '✨ Получен план вопросов', {
            session_id: sessionId,
            questions: wizardPlan?.questions?.length || 0,
          });

          const prefill = buildPrefillMap(answersPrefill);
          setPlan(wizardPlan);
          setPrefillMap(prefill);
          setIsWaiting(false);
          setConnectionError(null);

          updateFormData({
            wizardPlan: wizardPlan,
            wizardPrefill: prefill,
            wizardPrefillArray: answersPrefill,
            wizardCoverageReport: coverageReport,
            wizardPlanStatus: 'ready',
          });

          if (timeoutRef.current) {
            clearTimeout(timeoutRef.current);
            timeoutRef.current = null;
          }
          source.close();
          eventSourceRef.current = null;
        }
      } catch (err) {
        console.error('❌ Ошибка разбора события wizard:', err);
      }
    };

    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }
      if (eventSourceRef.current) {
        eventSourceRef.current.close();
        eventSourceRef.current = null;
      }
    };
  }, [isWaiting, formData.session_id, plan, updateFormData]);

  const handleRefreshPlan = () => {
    if (!formData.session_id) {
      message.error('Не найден session_id для подписки на события.');
      return;
    }
    setIsWaiting(true);
    setPlan(null);
    setConnectionError(null);
    updateFormData({
      wizardPlan: null,
      wizardPlanStatus: 'pending',
    });
  };

  const validateUploads = (values: Record<string, any>) => {
    // Проверяем каждый документ по его ID
    for (const doc of documents) {
      // Находим вопрос, к которому привязан документ
      const questionName = Object.keys(documentGroups).find(key => 
        documentGroups[key].some(d => d.id === doc.id)
      );
      
      if (!questionName) continue;
      const answer = values?.[questionName];
      if (!isAffirmative(answer)) continue;
      
      // Блоки теперь хранятся по doc.id, а не по questionName
      const docKey = doc.id || doc.name || `doc_${questionName}`;
      const blocks = questionFileBlocks[docKey] || [];
      
      // Проверяем, есть ли файлы для обязательного документа (если он не пропущен)
      if (doc.required) {
        if (skippedDocuments.has(docKey)) {
          continue; // Пропускаем валидацию для пропущенных документов
        }
        const hasFiles = blocks.some((block) => block.files.length > 0);
        if (!hasFiles) {
          return `Добавьте файлы для документа "${doc.name}" или отметьте, что документа нет`;
        }
      }
      
      // Проверяем описание только для необязательных документов И только если документ не предопределённый
      // Предопределённые документы (contract, payment, payment_confirmation, receipt, cheque) не требуют описания
      const docIdLower = (doc.id || '').toLowerCase();
      const docNameLower = (doc.name || '').toLowerCase();
      const isPredefinedDoc = doc.id && !doc.id.includes('_exist') && 
        (doc.id === 'contract' || doc.id === 'payment' || doc.id === 'payment_confirmation' || 
         docIdLower.includes('contract') || docIdLower.includes('payment') || 
         docIdLower.includes('receipt') || docIdLower.includes('cheque') ||
         docNameLower.includes('договор') || docNameLower.includes('чек') || 
         docNameLower.includes('оплат') || docNameLower.includes('платеж'));
      
      // Для обязательных документов описание не требуется
      // Для предопределённых документов описание не требуется
      if (!doc.required && !isPredefinedDoc) {
      const missingDescription = blocks.some(
        (block) => block.files.length > 0 && !block.description?.trim()
      );
      if (missingDescription) {
          return `Заполните описание для документа "${doc.name}"`;
      }
    }
    }
    
    const customMissingDescription = customFileBlocks.some(
      (block) => block.files.length > 0 && !block.description?.trim()
    );
    if (customMissingDescription) {
      return 'Заполните описание для дополнительных документов';
    }
    return null;
  };

  const handleFinish = async (values: Record<string, any>) => {
    const uploadError = validateUploads(values);
    if (uploadError) {
      message.error(uploadError);
      return;
    }

    // Сохраняем в общий стейт
    updateFormData({
      wizardPlan: plan,
      wizardAnswers: values,
      wizardPlanStatus: 'answered',
      wizardUploads: {
        documents: questionFileBlocks,
        custom: customFileBlocks,
      },
      wizardSkippedDocuments: Array.from(skippedDocuments),
    });

    addDebugEvent?.('wizard', 'info', '📝 Ответы на вопросы сохранены', {
      answers: values,
    });

    // Дёргаем вебхук через backend сразу после заполнения визарда (multipart/form-data)
    try {
      setSubmitting(true);
      addDebugEvent?.('wizard', 'info', '📤 Отправляем данные визарда в n8n', {
        session_id: formData.session_id,
      });

      const formPayload = new FormData();
      formPayload.append('stage', 'wizard');
      formPayload.append('form_id', 'ticket_form');
      if (formData.session_id) formPayload.append('session_id', formData.session_id);
      if (formData.clientIp) formPayload.append('client_ip', formData.clientIp);
      if (formData.smsCode) formPayload.append('sms_code', formData.smsCode);
      // Добавляем unified_id и claim_id (если есть)
      if (formData.unified_id) formPayload.append('unified_id', formData.unified_id);
      if (formData.claim_id) formPayload.append('claim_id', formData.claim_id);
      if (formData.contact_id) formPayload.append('contact_id', String(formData.contact_id));
      if (formData.project_id) formPayload.append('project_id', String(formData.project_id));
      if (typeof formData.is_new_contact !== 'undefined') {
        formPayload.append('is_new_contact', String(formData.is_new_contact));
      }
      if (typeof formData.is_new_project !== 'undefined') {
        formPayload.append('is_new_project', String(formData.is_new_project));
      }
      if (formData.phone) formPayload.append('phone', formData.phone);
      if (formData.email) formPayload.append('email', formData.email);
      if (formData.eventType) formPayload.append('event_type', formData.eventType);

      // JSON-поля
      formPayload.append('wizard_plan', JSON.stringify(plan || {}));
      formPayload.append('wizard_answers', JSON.stringify(values || {}));
      formPayload.append('wizard_skipped_documents', JSON.stringify(Array.from(skippedDocuments)));

      // --- Группируем блоки в uploads[i][j] + uploads_descriptions[i] + uploads_field_names[i]
      type UploadGroup = {
        index: number;
        question?: string;
        block: FileBlock;
        kind: 'question' | 'custom';
      };

      const groups: UploadGroup[] = [];
      let groupIndex = 0;

      // Собираем все блоки документов (теперь они хранятся по doc.id)
      // Сначала ищем блоки, которые привязаны к вопросам через documentGroups
      const allDocKeys = new Set<string>();
      Object.values(documentGroups).forEach(docs => {
        docs.forEach(doc => {
          const docKey = doc.id || doc.name;
          if (docKey && questionFileBlocks[docKey]) {
            allDocKeys.add(docKey);
          }
        });
      });
      
      // Также добавляем блоки по старым ключам (для обратной совместимости)
      Object.keys(questionFileBlocks).forEach(key => {
        if (!allDocKeys.has(key) && (key.includes('_exist') || key.startsWith('doc_'))) {
          allDocKeys.add(key);
        }
      });

      Array.from(allDocKeys).forEach((docKey) => {
        const blocks = questionFileBlocks[docKey] || [];
        blocks.forEach((block) => {
          groups.push({
            index: groupIndex++,
            question: docKey, // Используем docKey как идентификатор
            block,
            kind: 'question',
          });
        });
      });

      // Затем кастомные блоки
      customFileBlocks.forEach((block) => {
        groups.push({
          index: groupIndex++,
          question: 'custom',
          block,
          kind: 'custom',
        });
      });

      const guessFieldName = (group: UploadGroup): string => {
        const cat = (group.block.category || group.question || '').toLowerCase();
        
        // Определяем имя поля на основе категории (которая теперь равна doc.id)
        if (cat.includes('contract') || cat === 'contract' || cat === 'договор') {
          return 'upload_contract';
        }
        if (cat.includes('payment') || cat.includes('cheque') || cat.includes('receipt') || 
            cat.includes('подтверждение') || cat === 'payment_proof') {
            return 'upload_payment';
          }
        if (cat.includes('correspondence') || cat.includes('chat') || cat.includes('переписка')) {
          return 'upload_correspondence';
        }
        // Если категория похожа на ID документа, используем её
        if (cat && !cat.includes('_exist')) {
          return `upload_${cat.replace(/[^a-z0-9_]/g, '_')}`;
        }
        // Fallback на индекс
        return `upload_${group.index}`;
      };

      // ✅ Подсчитываем дубликаты labels для автоматической нумерации
      const labelCounts: Record<string, number> = {};
      const labelIndexes: Record<string, number> = {};
      
      // Первый проход - считаем сколько раз встречается каждый label
      groups.forEach((group) => {
        const block = group.block;
        const baseLabel = (block.description?.trim()) || block.docLabel || block.fieldName || guessFieldName(group);
        labelCounts[baseLabel] = (labelCounts[baseLabel] || 0) + 1;
      });

      groups.forEach((group) => {
        const i = group.index;
        const block = group.block;

        // Описание группы
        formPayload.append(
          `uploads_descriptions[${i}]`,
          block.description || ''
        );

        // Имя "поля" группы (используем docLabel если есть, иначе guessFieldName)
        const fieldLabel = block.docLabel || block.fieldName || guessFieldName(group);
        formPayload.append(
          `uploads_field_names[${i}]`,
          fieldLabel
        );
        
        // ✅ Добавляем реальное название поля (label) для использования в n8n
        // Приоритет: description (если заполнено) > docLabel > fieldLabel
        const baseLabel = (block.description?.trim()) || block.docLabel || fieldLabel;
        
        // ✅ Автоматическая нумерация для дубликатов
        let finalFieldLabel = baseLabel;
        if (labelCounts[baseLabel] > 1) {
          labelIndexes[baseLabel] = (labelIndexes[baseLabel] || 0) + 1;
          finalFieldLabel = `${baseLabel} #${labelIndexes[baseLabel]}`;
        }
        
        formPayload.append(
          `uploads_field_labels[${i}]`,
          finalFieldLabel
        );
        
        // 🔍 Логируем отправляемые метаданные документов
        console.log(`📁 Группа ${i}:`, {
          field_name: fieldLabel,
          field_label: finalFieldLabel,
          description: block.description,
          docLabel: block.docLabel,
          filesCount: block.files.length,
        });

        // Файлы: uploads[i][j]
        block.files.forEach((file, j) => {
          const origin: any = (file as any).originFileObj;
          if (!origin) return;
          formPayload.append(`uploads[${i}][${j}]`, origin, origin.name);
        });
      });

      // Логируем ключевые поля перед отправкой
      console.log('📤 Отправка в n8n:', {
        session_id: formData.session_id,
        unified_id: formData.unified_id,
        claim_id: formData.claim_id,
        contact_id: formData.contact_id,
        phone: formData.phone,
      });

      const response = await fetch('/api/v1/claims/wizard', {
        method: 'POST',
        body: formPayload,
      });

      const text = await response.text();
      let parsed: any = null;
      try {
        parsed = text ? JSON.parse(text) : null;
      } catch {
        parsed = null;
      }

      if (!response.ok) {
        message.error('Не удалось отправить данные визарда. Попробуйте ещё раз.');
        addDebugEvent?.('wizard', 'error', '❌ Ошибка отправки визарда в n8n', {
          status: response.status,
          body: text,
        });
        return;
      }

      addDebugEvent?.('wizard', 'success', '✅ Визард отправлен в n8n', {
        response: parsed ?? text,
      });
      message.success('Мы изучаем ваш вопрос и документы.');
      
      // Подписываемся на канал claim:plan для получения данных заявления
      if (formData.session_id) {
        subscribeToClaimPlan(formData.session_id);
      } else {
        console.warn('⚠️ session_id отсутствует, не можем подписаться на claim:plan');
        onNext();
      }
    } catch (error) {
      message.error('Ошибка соединения при отправке визарда.');
      addDebugEvent?.('wizard', 'error', '❌ Ошибка соединения при отправке визарда', {
        error: String(error),
      });
      onNext();
    } finally {
      setSubmitting(false);
    }
  };
  
  // Функция подписки на канал claim:plan
  const subscribeToClaimPlan = useCallback((sessionToken: string) => {
    console.log('📡 Подписка на канал claim:plan для session:', sessionToken);
    
    // Закрываем предыдущее соединение, если есть
    if (eventSourceRef.current) {
      eventSourceRef.current.close();
      eventSourceRef.current = null;
    }
    
    // Создаём новое SSE соединение
    const eventSource = new EventSource(`/api/v1/claim-plan/${sessionToken}`);
    eventSourceRef.current = eventSource;
    
    eventSource.onopen = () => {
      console.log('✅ Подключено к каналу claim:plan');
      addDebugEvent?.('claim-plan', 'info', '📡 Ожидание данных заявления...');
      message.loading('Ожидание данных заявления...', 0);
    };
    
    eventSource.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        console.log('📥 Получены данные из claim:plan:', data);
        
        if (data.event_type === 'claim_plan_ready' && data.status === 'ready') {
          // Данные заявления получены!
          message.destroy(); // Убираем loading сообщение
          message.success('Данные заявления готовы!');
          
          // Сохраняем данные заявления в formData
          updateFormData({
            claimPlanData: data.data, // Данные от n8n
            showClaimConfirmation: true, // Флаг для показа формы подтверждения
          });
          
          // Закрываем SSE соединение
          eventSource.close();
          eventSourceRef.current = null;
          
          // Переходим к следующему шагу (форма подтверждения)
    onNext();
        } else if (data.event_type === 'claim_plan_error' || data.status === 'error') {
          message.destroy();
          message.error(data.message || 'Ошибка получения данных заявления');
          eventSource.close();
          eventSourceRef.current = null;
          onNext(); // Переходим дальше даже при ошибке
        } else if (data.event_type === 'claim_plan_timeout' || data.status === 'timeout') {
          message.destroy();
          message.warning('Превышено время ожидания. Попробуйте обновить страницу.');
          eventSource.close();
          eventSourceRef.current = null;
          onNext();
        }
      } catch (error) {
        console.error('❌ Ошибка парсинга данных из claim:plan:', error);
        message.destroy();
        message.error('Ошибка обработки данных заявления');
      }
    };
    
    eventSource.onerror = (error) => {
      console.error('❌ Ошибка SSE соединения claim:plan:', error);
      message.destroy();
      message.error('Ошибка подключения к серверу');
      eventSource.close();
      eventSourceRef.current = null;
      onNext(); // Переходим дальше даже при ошибке
    };
    
    // Таймаут на 5 минут
    timeoutRef.current = setTimeout(() => {
      console.warn('⏰ Таймаут ожидания данных заявления');
      message.destroy();
      message.warning('Превышено время ожидания данных заявления');
      eventSource.close();
      eventSourceRef.current = null;
      onNext();
    }, 300000); // 5 минут
  }, [addDebugEvent, updateFormData, onNext]);

  const renderQuestionField = (question: WizardQuestion) => {
    // Обработка по input_type для более точного определения типа поля
    if (question.input_type === 'multi_choice' || question.control === 'input[type="checkbox"]') {
      return (
        <Checkbox.Group>
          <Space direction="vertical">
            {question.options?.map((option) => (
              <Checkbox key={option.value} value={option.value}>
                {option.label}
              </Checkbox>
            ))}
          </Space>
        </Checkbox.Group>
      );
    }

    switch (question.control) {
      case 'textarea':
      case 'input[type="textarea"]':
        return (
          <TextArea
            rows={4}
            placeholder="Ответ"
            autoSize={{ minRows: 3, maxRows: 6 }}
          />
        );
      case 'input[type="date"]':
        return (
          <Input 
            type="date" 
            size="large" 
            placeholder="Выберите дату"
          />
        );
      case 'input[type="radio"]':
        return (
          <Radio.Group>
            <Space direction="vertical">
              {question.options?.map((option) => (
                <Radio key={option.value} value={option.value}>
                  {option.label}
                </Radio>
              ))}
            </Space>
          </Radio.Group>
        );
      default:
        return <Input size="large" placeholder="Ответ" />;
    }
  };

  const renderDocumentBlocks = (docId: string, docList: WizardDocument[]) => {
    const currentBlocks = questionFileBlocks[docId] || [];
    const docLabel = docList.map((doc) => doc.name).join(', ');
    const accept = docList.flatMap((doc) => doc.accept || []);
    const uniqueAccept = Array.from(new Set(accept.length ? accept : ['pdf', 'jpg', 'png']));
    
    // Документ предопределён если у него есть id и он НЕ общий (не содержит _exist)
    // Для предустановленных документов НЕ показываем поле описания и кнопку "Удалить"
    const doc = docList[0];
    const isPredefinedDoc = docList.length === 1 && doc && doc.id && !doc.id.includes('_exist');
    const singleDocName = doc?.name || docLabel;
    const isRequired = docList.some(doc => doc.required);
    const isSkipped = skippedDocuments.has(docId);

    return (
      <Space direction="vertical" style={{ width: '100%' }}>
        {/* Если документ пропущен - показываем только сообщение */}
        {isSkipped && (
          <div style={{ padding: 12, background: '#fff7e6', borderRadius: 8, border: '1px solid #ffd591' }}>
            <Checkbox
              checked={isSkipped}
              onChange={(e) => {
                const newSkipped = new Set(skippedDocuments);
                if (e.target.checked) {
                  newSkipped.add(docId);
                } else {
                  newSkipped.delete(docId);
                }
                setSkippedDocuments(newSkipped);
                updateFormData({ wizardSkippedDocuments: Array.from(newSkipped) });
              }}
            >
              <Text type="warning">У меня нет документа: {docLabel}</Text>
            </Checkbox>
          </div>
        )}
        
        {!isSkipped && currentBlocks.map((block, idx) => (
          <Card
            key={block.id}
            size="small"
            style={{
              borderRadius: 8,
              border: '1px solid #d9d9d9',
              background: '#fff',
            }}
            title={singleDocName || `${docLabel} — группа #${idx + 1}`}
            extra={
              // Кнопка "Удалить" только если это дополнительный блок (idx > 0)
              // Первый блок предустановленного документа удалять нельзя
              (currentBlocks.length > 1 && idx > 0) && (
              <Button
                type="link"
                danger
                size="small"
                onClick={() => removeDocumentBlock(docId, block.id)}
              >
                Удалить
              </Button>
              )
            }
          >
            <Space direction="vertical" style={{ width: '100%' }}>
              {/* Поле описания показываем только для дополнительных блоков (idx > 0)
                  или для общих документов (docs_exist) */}
              {(idx > 0 || !isPredefinedDoc) && (
              <Input
                  placeholder="Уточните тип документа (например: Претензия от 12.05)"
                value={block.description}
                onChange={(e) =>
                  updateDocumentBlock(docId, block.id, { description: e.target.value })
                }
              />
              )}
              
              {/* Выпадашка категорий только для общих вопросов (docs_exist, correspondence_exist) */}
              {!isPredefinedDoc && (
              <Select
                value={block.category || docId}
                onChange={(value) => updateDocumentBlock(docId, block.id, { category: value })}
                placeholder="Категория блока"
              >
                {documentCategoryOptions.map((option) => (
                  <Option key={`${docId}-${option.value}`} value={option.value}>
                    {option.label}
                  </Option>
                ))}
              </Select>
              )}
              
              <Dragger
                multiple
                beforeUpload={() => false}
                fileList={block.files}
                onChange={({ fileList }) =>
                  updateDocumentBlock(docId, block.id, { files: fileList })
                }
                accept={uniqueAccept.map((ext) => `.${ext}`).join(',')}
                style={{ background: '#fafafa' }}
              >
                <p className="ant-upload-drag-icon">
                  <LoadingOutlined style={{ color: '#595959' }} />
                </p>
                <p className="ant-upload-text">Перетащите файлы или нажмите для загрузки</p>
                <p className="ant-upload-hint">
                  Допустимые форматы: {uniqueAccept.join(', ')}. До 5 файлов, максимум 20 МБ каждый.
                </p>
              </Dragger>
              
              {/* Чекбокс "Нет документа" под загрузкой - только для обязательных и только в первом блоке */}
              {isRequired && idx === 0 && block.files.length === 0 && (
                <Checkbox
                  checked={false}
                  onChange={(e) => {
                    if (e.target.checked) {
                      const newSkipped = new Set(skippedDocuments);
                      newSkipped.add(docId);
                      setSkippedDocuments(newSkipped);
                      updateFormData({ wizardSkippedDocuments: Array.from(newSkipped) });
                    }
                  }}
                  style={{ marginTop: 8 }}
                >
                  <Text type="secondary">У меня нет этого документа</Text>
                </Checkbox>
              )}
            </Space>
          </Card>
        ))}
        {/* Кнопка "Добавить" только если документ не пропущен */}
        {!isSkipped && (!isPredefinedDoc || currentBlocks.length === 0) && (
        <Button
          icon={<PlusOutlined />}
            onClick={() => addDocumentBlock(docId, docLabel, docList)}
          style={{ width: '100%' }}
        >
            {isPredefinedDoc && currentBlocks.length === 0 
              ? `Загрузить ${singleDocName || docLabel}`
              : `Добавить документы (${docLabel})`}
        </Button>
        )}
      </Space>
    );
  };

  const renderCustomUploads = () => (
    <Card
      size="small"
      style={{ marginTop: 24, borderRadius: 8, border: '1px solid #d9d9d9' }}
      title="Документы"
      extra={
        <Button type="link" onClick={addCustomBlock} icon={<PlusOutlined />}>
          Добавить блок
        </Button>
      }
    >
      {customFileBlocks.length === 0 && (
        <Paragraph type="secondary" style={{ marginBottom: 16 }}>
          Можно добавить произвольные группы документов — например, переписку, дополнительные акты
          или фото.
        </Paragraph>
      )}
      <Space direction="vertical" style={{ width: '100%' }}>
        {customFileBlocks.map((block, idx) => (
          <Card
            key={block.id}
            size="small"
            type="inner"
            title={`Группа #${idx + 1}`}
            extra={
              <Button type="link" danger size="small" onClick={() => removeCustomBlock(block.id)}>
                Удалить
              </Button>
            }
          >
            <Space direction="vertical" style={{ width: '100%' }}>
              <Select
                value={block.category}
                placeholder="Категория"
                onChange={(value) => updateCustomBlock(block.id, { category: value })}
                allowClear
              >
                {customCategoryOptions.map((option) => (
                  <Option key={`custom-${option.value}`} value={option.value}>
                    {option.label}
                  </Option>
                ))}
              </Select>
              <TextArea
                placeholder="Описание (например: переписка в WhatsApp с менеджером)"
                autoSize={{ minRows: 2, maxRows: 4 }}
                value={block.description}
                onChange={(e) => updateCustomBlock(block.id, { description: e.target.value })}
              />
              <Dragger
                multiple
                beforeUpload={() => false}
                fileList={block.files}
                onChange={({ fileList }) => updateCustomBlock(block.id, { files: fileList })}
                accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,.heic"
              >
                <p className="ant-upload-drag-icon">
                  <LoadingOutlined style={{ color: '#595959' }} />
                </p>
                <p className="ant-upload-text">Перетащите файлы или нажмите для загрузки</p>
                <p className="ant-upload-hint">Максимум 10 файлов, до 20 МБ каждый.</p>
              </Dragger>
            </Space>
          </Card>
        ))}
        {customFileBlocks.length > 0 && (
          <Button onClick={addCustomBlock} icon={<PlusOutlined />}>
            Добавить ещё документы
          </Button>
        )}
      </Space>
    </Card>
  );

  const renderQuestions = () => {
    console.log('🔍 StepWizardPlan renderQuestions:', {
      questionsCount: questions.length,
      documentsCount: documents.length,
      questions: questions.map(q => ({ name: q.name, label: q.label, input_type: q.input_type, required: q.required }))
    });
    
    return (
    <>
      <Card
        size="small"
        style={{ marginBottom: 16, borderRadius: 8, border: '1px solid #d9d9d9' }}
      >
        <Space direction="vertical" style={{ width: '100%' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            <Text strong>Прогресс заполнения</Text>
            <Text type="secondary">
              {progressState.done}/{progressState.total} обязательных ответов
            </Text>
          </div>
          <Progress percent={progressPercent} showInfo={false} />
        </Space>
      </Card>
      <Form
        form={form}
        layout="vertical"
        onFinish={handleFinish}
        initialValues={{ ...prefillMap, ...formData.wizardAnswers }}
      >
      {questions.map((question) => {
        // Для условных полей используем shouldUpdate для отслеживания изменений
        const hasCondition = !!question.ask_if;
        
        return (
          <Form.Item 
            key={question.name}
            shouldUpdate={hasCondition ? (prev, curr) => {
              // Обновляем только если изменилось значение поля, от которого зависит вопрос
              return prev[question.ask_if!.field] !== curr[question.ask_if!.field];
            } : true} // ✅ Для безусловных полей shouldUpdate=true, чтобы render function работала
          >
          {() => {
            const values = form.getFieldsValue(true);
            if (!evaluateCondition(question.ask_if, values)) {
                console.log(`⏭️ Question ${question.name} skipped: condition not met`, question.ask_if, values);
              return null;
            }
            const questionDocs = documentGroups[question.name] || [];
            const questionValue = values?.[question.name];
              
              // Скрываем вопросы, которые связаны с загрузкой документов
              // Если в плане визарда есть документы, не показываем поля про загрузку (text/textarea/file)
              const questionLabelLower = (question.label || '').toLowerCase();
              const questionNameLower = (question.name || '').toLowerCase();
              
              // Скрываем вопрос docs_exist (чекбоксы "какие документы есть") если есть документы
              // Загрузка документов реализована через отдельные блоки под информационной карточкой
              const isDocsExistQuestion = questionNameLower === 'docs_exist' || 
                                          questionNameLower === 'correspondence_exist' ||
                                          questionNameLower.includes('docs_exist');
              if (isDocsExistQuestion && documents.length > 0) {
                console.log(`🚫 Question ${question.name} hidden: docs_exist with documents`);
                return null;
              }
              
              const isDocumentUploadQuestion = 
                (question.input_type === 'text' || 
                 question.input_type === 'textarea' || 
                 question.input_type === 'file') &&
                (questionLabelLower.includes('загрузите') || 
                 questionLabelLower.includes('фото') ||
                 questionLabelLower.includes('сканы') ||
                 questionLabelLower.includes('документ') ||
                 questionLabelLower.includes('договор') ||
                 questionLabelLower.includes('чек') ||
                 questionLabelLower.includes('платеж') ||
                 questionLabelLower.includes('копии') ||
                 questionLabelLower.includes('переписк') ||
                 questionNameLower.includes('upload') ||
                 questionNameLower.includes('document'));
              
              // Если это вопрос про загрузку документов И в плане есть документы, не показываем поле
              // (даже если вопрос не связан с documentGroups)
              // Загрузка файлов уже реализована через блоки документов (documents)
              if (isDocumentUploadQuestion && documents.length > 0) {
                console.log(`🚫 Question ${question.name} hidden: isDocumentUploadQuestion=true, documents.length=${documents.length}`);
                return null;
              }
              
              console.log(`✅ Question ${question.name} will render:`, { input_type: question.input_type, label: question.label, required: question.required });
              
            return (
              <>
                <Form.Item
                  label={question.label}
                  name={question.name}
                  rules={[
                    {
                      required: question.required,
                      message: 'Поле обязательно для заполнения',
                    },
                  ]}
                >
                  {renderQuestionField(question)}
                </Form.Item>
                {questionDocs.length > 0 && isAffirmative(questionValue) && (
                  <div style={{ marginBottom: 24 }}>
                    <Text strong>Загрузите документы:</Text>
                      <Space direction="vertical" style={{ width: '100%', marginTop: 16 }}>
                        {questionDocs.map((doc) => {
                          // Используем doc.id как ключ для отдельного хранения блоков каждого документа
                          const docKey = doc.id || doc.name || `doc_${question.name}`;
                          return (
                            <div key={doc.id}>
                              {renderDocumentBlocks(docKey, [doc])}
                            </div>
                          );
                        })}
                      </Space>
                  </div>
                )}
              </>
            );
          }}
        </Form.Item>
        );
      })}

      <Space style={{ marginTop: 24 }}>
        <Button onClick={onPrev}>← Назад</Button>
        <Button type="primary" htmlType="submit" loading={submitting}>
          Сохранить и продолжить →
        </Button>
      </Space>
      </Form>
      {renderCustomUploads()}
    </>
  );
  };

  if (!formData.session_id) {
    return (
      <Result
        status="warning"
        title="Нет session_id"
        subTitle="Не удалось определить идентификатор сессии. Вернитесь на предыдущий шаг и попробуйте снова."
        extra={<Button onClick={onPrev}>Вернуться</Button>}
      />
    );
  }

  // ✅ НОВЫЙ ФЛОУ: Если есть documents_required, показываем загрузку документов
  const documentsRequired = formData.documents_required || [];
  const hasNewFlowDocs = documentsRequired.length > 0;
  
  // 🔍 ОТЛАДКА: Логируем состояние для диагностики
  console.log('🔍 StepWizardPlan - определение флоу:', {
    documentsRequiredCount: documentsRequired.length,
    documentsRequired: documentsRequired,
    hasNewFlowDocs,
    hasPlan: !!plan,
    isWaiting,
    formDataKeys: Object.keys(formData),
  });
  
  // Состояние для поэкранной загрузки документов (новый флоу)
  // Убираем дубликаты при инициализации
  const initialUploadedDocs = formData.documents_uploaded?.map((d: any) => d.type || d.id) || [];
  const [uploadedDocs, setUploadedDocs] = useState<string[]>(Array.from(new Set(initialUploadedDocs)));
  const [skippedDocs, setSkippedDocs] = useState<string[]>(formData.documents_skipped || []);
  
  // Отладка: логируем инициализацию
  useEffect(() => {
    console.log('🔍 Инициализация документов:', {
      documentsRequiredCount: documentsRequired.length,
      initialUploadedDocs,
      uploadedDocs,
      skippedDocs,
      formDataCurrentDocIndex: formData.current_doc_index,
    });
  }, []); // Только при первой загрузке
  
  // Находим первый незагруженный документ при инициализации
  const findFirstUnprocessedDoc = useCallback((startIndex: number = 0) => {
    for (let i = startIndex; i < documentsRequired.length; i++) {
      const doc = documentsRequired[i];
      const docId = doc.id || doc.name;
      if (!uploadedDocs.includes(docId) && !skippedDocs.includes(docId)) {
        return i;
      }
    }
    return documentsRequired.length; // Все документы обработаны
  }, [documentsRequired, uploadedDocs, skippedDocs]);
  
  const [currentDocIndex, setCurrentDocIndex] = useState(() => {
    const savedIndex = formData.current_doc_index || 0;
    // Используем initialUploadedDocs и formData.documents_skipped для инициализации
    const initUploaded = Array.from(new Set(initialUploadedDocs));
    const initSkipped = formData.documents_skipped || [];
    
    // Находим первый незагруженный документ
    // Сначала проверяем с сохранённого индекса, потом с начала
    let firstUnprocessed = documentsRequired.length; // По умолчанию - все обработаны
    
    // Проверяем с сохранённого индекса до конца
    for (let i = savedIndex; i < documentsRequired.length; i++) {
      const doc = documentsRequired[i];
      const docId = doc.id || doc.name;
      if (!initUploaded.includes(docId) && !initSkipped.includes(docId)) {
        firstUnprocessed = i;
        break;
      }
    }
    
    // Если не нашли с сохранённого индекса, проверяем с начала до сохранённого
    if (firstUnprocessed === documentsRequired.length) {
      for (let i = 0; i < savedIndex; i++) {
        const doc = documentsRequired[i];
        const docId = doc.id || doc.name;
        if (!initUploaded.includes(docId) && !initSkipped.includes(docId)) {
          firstUnprocessed = i;
          break;
        }
      }
    }
    
    console.log('🔍 Инициализация currentDocIndex:', {
      savedIndex,
      firstUnprocessed,
      documentsRequiredLength: documentsRequired.length,
      initUploaded,
      initSkipped,
      documentsRequiredList: documentsRequired.map((d: any) => ({
        id: d.id || d.name,
        name: d.name,
        uploaded: initUploaded.includes(d.id || d.name),
        skipped: initSkipped.includes(d.id || d.name),
      })),
    });
    // Убеждаемся, что индекс не выходит за границы
    return Math.min(firstUnprocessed, documentsRequired.length);
  });
  
  // Исправляем currentDocIndex только если он выходит за границы или указывает на уже обработанный документ
  useEffect(() => {
    if (documentsRequired.length === 0) return;
    
    // Если текущий индекс выходит за границы, исправляем
    if (currentDocIndex >= documentsRequired.length) {
      const firstUnprocessed = findFirstUnprocessedDoc(0);
      console.log('🔄 Исправление currentDocIndex (выход за границы):', {
        currentIndex: currentDocIndex,
        documentsRequiredLength: documentsRequired.length,
        firstUnprocessed,
      });
      setCurrentDocIndex(firstUnprocessed);
      updateFormData({ current_doc_index: firstUnprocessed });
      return;
    }
    
    // Если текущий документ уже обработан, переходим к следующему
    const currentDoc = documentsRequired[currentDocIndex];
    if (currentDoc) {
      const docId = currentDoc.id || currentDoc.name;
      if (uploadedDocs.includes(docId) || skippedDocs.includes(docId)) {
        const firstUnprocessed = findFirstUnprocessedDoc(currentDocIndex + 1);
        console.log('🔄 Исправление currentDocIndex (документ уже обработан):', {
          currentIndex: currentDocIndex,
          currentDocId: docId,
          firstUnprocessed,
        });
        setCurrentDocIndex(firstUnprocessed);
        updateFormData({ current_doc_index: firstUnprocessed });
      }
    }
  }, [currentDocIndex, documentsRequired.length, uploadedDocs, skippedDocs, findFirstUnprocessedDoc, updateFormData]);
  
  const [docChoice, setDocChoice] = useState<'upload' | 'none'>('upload');  // Выбор: загрузить или нет документа (по умолчанию - загрузить)
  const [currentUploadedFiles, setCurrentUploadedFiles] = useState<any[]>([]);  // Массив загруженных файлов
  
  // Текущий документ для загрузки
  const currentDoc = documentsRequired[currentDocIndex];
  const isLastDoc = currentDocIndex >= documentsRequired.length - 1;
  
  // Проверяем, что ВСЕ документы либо загружены, либо пропущены
  const allDocsProcessed = useMemo(() => {
    // Проверяем каждый документ из documentsRequired
    const allRequiredDocsProcessed = documentsRequired.every((doc: any) => {
      const docId = doc.id || doc.name;
      return uploadedDocs.includes(docId) || skippedDocs.includes(docId);
    });
    
    const processedCount = uploadedDocs.length + skippedDocs.length;
    const allProcessed = allRequiredDocsProcessed && processedCount >= documentsRequired.length;
    
    console.log('🔍 Проверка завершённости:', {
      uploadedDocs: uploadedDocs.length,
      skippedDocs: skippedDocs.length,
      totalRequired: documentsRequired.length,
      processedCount,
      allRequiredDocsProcessed,
      allProcessed,
      uploadedDocsList: uploadedDocs,
      skippedDocsList: skippedDocs,
      requiredDocsList: documentsRequired.map((d: any) => {
        const docId = d.id || d.name;
        return {
          id: docId,
          name: d.name,
          uploaded: uploadedDocs.includes(docId),
          skipped: skippedDocs.includes(docId),
        };
      }),
    });
    
    return allProcessed;
  }, [uploadedDocs, skippedDocs, documentsRequired]);
  
  // Отладка: логируем состояние текущего документа
  useEffect(() => {
    console.log('🔍 Текущий документ для загрузки:', {
      currentDocIndex,
      documentsRequiredLength: documentsRequired.length,
      currentDoc: currentDoc ? { id: currentDoc.id, name: currentDoc.name } : null,
      uploadedDocs,
      skippedDocs,
      allDocsProcessed,
    });
  }, [currentDocIndex, documentsRequired.length, currentDoc, uploadedDocs, skippedDocs, allDocsProcessed]);
  
  // Автоматически пропускаем уже загруженные документы
  useEffect(() => {
    if (!currentDoc || allDocsProcessed) return;
    
    const docId = currentDoc.id || currentDoc.name;
    const isAlreadyUploaded = uploadedDocs.includes(docId);
    const isAlreadySkipped = skippedDocs.includes(docId);
    
    if (isAlreadyUploaded || isAlreadySkipped) {
      console.log(`⏭️ Документ "${currentDoc.name}" уже обработан, переходим к следующему`);
      const nextIndex = findFirstUnprocessedDoc(currentDocIndex + 1);
      
      // Обновляем только если следующий индекс отличается от текущего
      if (nextIndex !== currentDocIndex) {
        setCurrentDocIndex(nextIndex);
        updateFormData({
          current_doc_index: nextIndex,
        });
      }
    }
  }, [currentDoc, uploadedDocs, skippedDocs, currentDocIndex, allDocsProcessed, findFirstUnprocessedDoc, updateFormData]);
  
  // Обработчик выбора файлов (НЕ отправляем сразу, только сохраняем)
  const handleFilesChange = (fileList: any[]) => {
    console.log('📁 handleFilesChange:', fileList.length, 'файлов', fileList.map(f => f.name));
    setCurrentUploadedFiles(fileList);
    if (fileList.length > 0) {
      setDocChoice('upload');
    }
  };
  
  // Обработчик "Продолжить" — отправляем файл или пропускаем
  const handleDocContinue = async () => {
    if (!currentDoc) return;
    
    // Если выбрано "Нет документа" — пропускаем
    if (docChoice === 'none') {
      if (currentDoc.required) {
        message.warning(`⚠️ Документ "${currentDoc.name}" важен для рассмотрения заявки. Постарайтесь найти его позже.`);
      }
      
      const newSkipped = [...skippedDocs, currentDoc.id];
      setSkippedDocs(newSkipped);
      
      // Находим следующий незагруженный документ (используем обновлённый список)
      const findNextUnprocessed = (startIndex: number) => {
        for (let i = startIndex; i < documentsRequired.length; i++) {
          const doc = documentsRequired[i];
          const docId = doc.id || doc.name;
          if (!uploadedDocs.includes(docId) && !newSkipped.includes(docId)) {
            return i;
          }
        }
        return documentsRequired.length;
      };
      const nextIndex = findNextUnprocessed(currentDocIndex + 1);
      
      updateFormData({
        documents_skipped: newSkipped,
        current_doc_index: nextIndex,
      });
      
      // Переход к следующему незагруженному документу
      setCurrentDocIndex(nextIndex);
      return;
    }
    
    // Если выбрано "Загрузить" — отправляем все файлы ОДНИМ запросом
    if (docChoice === 'upload' && currentUploadedFiles.length > 0) {
      try {
        setSubmitting(true);
        
        console.log('📤 Загружаем все файлы одним запросом:', {
          totalFiles: currentUploadedFiles.length,
          files: currentUploadedFiles.map(f => ({ name: f.name, uid: f.uid, size: f.size }))
        });
        
        const formDataToSend = new FormData();
        formDataToSend.append('claim_id', formData.claim_id || '');
        formDataToSend.append('session_id', formData.session_id || '');
        formDataToSend.append('unified_id', formData.unified_id || '');
        formDataToSend.append('contact_id', formData.contact_id || '');
        formDataToSend.append('phone', formData.phone || '');
        formDataToSend.append('document_type', currentDoc.id);
        formDataToSend.append('document_name', currentDoc.name || currentDoc.id);
        formDataToSend.append('document_description', currentDoc.hints || '');
        formDataToSend.append('group_index', String(currentDocIndex)); // ✅ Передаём индекс документа для правильного field_name
        
        // Добавляем все файлы в один запрос
        currentUploadedFiles.forEach((file) => {
          formDataToSend.append('files', file.originFileObj, file.name);
        });
        
        const response = await fetch('/api/v1/documents/upload-multiple', {
          method: 'POST',
          body: formDataToSend,
        });
        
        if (!response.ok) {
          const errorData = await response.json().catch(() => ({}));
          throw new Error(errorData.detail || 'Ошибка загрузки файлов');
        }
        
        const result = await response.json();
        console.log('✅ Все файлы загружены:', result);
        
        // Обновляем состояние
        const uploadedDocsData = [...(formData.documents_uploaded || [])];
        
        // Добавляем информацию о каждом загруженном файле
        result.file_ids.forEach((fileId: string, i: number) => {
          uploadedDocsData.push({
            type: currentDoc.id,
            file_id: fileId,
            filename: currentUploadedFiles[i]?.name || `file_${i}`,
            ocr_status: 'processing',
          });
        });
        
        message.success(`${currentDoc.name}: загружено ${result.files_count} файл(ов)!`);
        
        // Убираем дубликаты при добавлении
        const newUploaded = uploadedDocs.includes(currentDoc.id) 
          ? uploadedDocs 
          : [...uploadedDocs, currentDoc.id];
        setUploadedDocs(newUploaded);
        
        // Находим следующий незагруженный документ (используем обновлённый список)
        const findNextUnprocessed = (startIndex: number) => {
          for (let i = startIndex; i < documentsRequired.length; i++) {
            const doc = documentsRequired[i];
            const docId = doc.id || doc.name;
            if (!newUploaded.includes(docId) && !skippedDocs.includes(docId)) {
              return i;
            }
          }
          return documentsRequired.length;
        };
        const nextIndex = findNextUnprocessed(currentDocIndex + 1);
        
        updateFormData({
          documents_uploaded: uploadedDocsData,
          current_doc_index: nextIndex,
        });
        
        // Переход к следующему незагруженному документу
        setCurrentDocIndex(nextIndex);
        
      } catch (error: any) {
        message.error(`Ошибка загрузки: ${error.message}`);
        console.error('Upload error:', error);
      } finally {
        setSubmitting(false);
      }
    }
  };
  
  // Можно ли нажать "Продолжить"
  const canContinue = docChoice === 'none' || (docChoice === 'upload' && currentUploadedFiles.length > 0);
  
  // Сброс состояния при переходе к следующему документу
  useEffect(() => {
    setDocChoice('upload');
    setCurrentUploadedFiles([]);
  }, [currentDocIndex]);
  
  // Все документы загружены — переход к ожиданию заявления
  const handleAllDocsComplete = () => {
    message.loading('Формируем заявление...', 0);
    // TODO: Переход к StepWaitingClaim или показ loader
    onNext();
  };

  return (
    <div style={{ marginTop: 24 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
        <Button onClick={onPrev}>← Назад</Button>
        {plan && !hasNewFlowDocs && (
          <Button type="link" onClick={handleRefreshPlan}>
            Обновить рекомендации
          </Button>
        )}
      </div>

      <Card
        style={{
          borderRadius: 8,
          border: '1px solid #d9d9d9',
          background: '#fafafa',
        }}
      >
        {/* ✅ НОВЫЙ ФЛОУ: Поэкранная загрузка документов */}
        {hasNewFlowDocs && !allDocsProcessed && currentDocIndex < documentsRequired.length && currentDoc ? (
          <div style={{ padding: '24px 0' }}>
            {/* Прогресс */}
            <div style={{ marginBottom: 24 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
                <Text type="secondary">Документ {currentDocIndex + 1} из {documentsRequired.length}</Text>
                <Text type="secondary">{Math.round(((uploadedDocs.length + skippedDocs.length) / documentsRequired.length) * 100)}% завершено</Text>
              </div>
              <Progress 
                percent={Math.round(((uploadedDocs.length + skippedDocs.length) / documentsRequired.length) * 100)} 
                showInfo={false}
                strokeColor="#595959"
              />
            </div>
            
            {/* Заголовок документа */}
            <Title level={4} style={{ marginBottom: 8 }}>
              📄 {currentDoc.name}
              {currentDoc.required && <Tag color="volcano" style={{ marginLeft: 8 }}>Важный</Tag>}
            </Title>
            
            {currentDoc.hints && (
              <Paragraph type="secondary" style={{ marginBottom: 16 }}>
                {currentDoc.hints}
              </Paragraph>
            )}
            
            {/* Радио-кнопки выбора */}
            <Radio.Group 
              value={docChoice} 
              onChange={(e) => {
                setDocChoice(e.target.value);
                if (e.target.value === 'none') {
                  setCurrentUploadedFiles([]);
                }
              }}
              style={{ marginBottom: 16, display: 'block' }}
            >
              <Space direction="vertical" style={{ width: '100%' }}>
                <Radio value="upload" style={{ fontSize: 16 }}>
                  📎 Загрузить документ
                </Radio>
                <Radio value="none" style={{ fontSize: 16 }}>
                  ❌ У меня нет этого документа
                </Radio>
              </Space>
            </Radio.Group>
            
            {/* Загрузка файлов — показываем только если выбрано "Загрузить" */}
            {docChoice === 'upload' && (
              <Dragger
                multiple={true}
                beforeUpload={() => false}
                fileList={currentUploadedFiles}
                onChange={({ fileList }) => handleFilesChange(fileList)}
                onRemove={(file) => {
                  setCurrentUploadedFiles(prev => prev.filter(f => f.uid !== file.uid));
                  return true;
                }}
                accept={currentDoc.accept?.map((ext: string) => `.${ext}`).join(',') || '.pdf,.jpg,.jpeg,.png'}
                disabled={submitting}
                style={{ marginBottom: 24 }}
              >
                <p className="ant-upload-drag-icon">
                  <InboxOutlined style={{ color: '#595959', fontSize: 32 }} />
                </p>
                <p className="ant-upload-text">
                  Перетащите файлы или нажмите для выбора
                </p>
                <p className="ant-upload-hint">
                  📌 Можно загрузить несколько файлов (все страницы документа)
                  <br />
                  Форматы: {currentDoc.accept?.join(', ') || 'PDF, JPG, PNG'} (до 20 МБ каждый)
                </p>
              </Dragger>
            )}
            
            {/* Предупреждение если "нет документа" для важного */}
            {docChoice === 'none' && currentDoc.required && (
              <div style={{ 
                padding: 12, 
                background: '#fff7e6', 
                border: '1px solid #ffd591',
                borderRadius: 8, 
                marginBottom: 16 
              }}>
                <Text type="warning">
                  ⚠️ Этот документ важен для рассмотрения заявки. Постарайтесь найти его позже.
                </Text>
              </div>
            )}
            
            {/* Кнопки */}
            <Space style={{ marginTop: 16 }}>
              <Button onClick={onPrev}>← Назад</Button>
              <Button 
                type="primary" 
                onClick={handleDocContinue} 
                disabled={!canContinue || submitting}
                loading={submitting}
              >
                {submitting ? 'Загружаем...' : 'Продолжить →'}
              </Button>
            </Space>
            
            {/* Уже загруженные */}
            {uploadedDocs.length > 0 && (
              <div style={{ marginTop: 24, padding: 12, background: '#f6ffed', borderRadius: 8 }}>
                <Text strong>✅ Загружено:</Text>
                <ul style={{ margin: '8px 0 0 20px', padding: 0 }}>
                  {/* Убираем дубликаты и используем уникальные ключи */}
                  {Array.from(new Set(uploadedDocs)).map((docId, idx) => {
                    const doc = documentsRequired.find((d: any) => d.id === docId);
                    return <li key={`${docId}_${idx}`}>{doc?.name || docId}</li>;
                  })}
                </ul>
              </div>
            )}
          </div>
        ) : hasNewFlowDocs && !allDocsProcessed && currentDocIndex >= documentsRequired.length ? (
          <div style={{ padding: '24px 0', textAlign: 'center' }}>
            <Text type="warning">
              ⚠️ Ошибка: индекс документа ({currentDocIndex}) выходит за границы массива ({documentsRequired.length}).
              <br />
              Загружено: {uploadedDocs.length}, пропущено: {skippedDocs.length}
            </Text>
            <Button 
              type="primary" 
              style={{ marginTop: 16 }}
              onClick={() => {
                const nextIndex = findFirstUnprocessedDoc(0);
                setCurrentDocIndex(nextIndex);
                updateFormData({ current_doc_index: nextIndex });
              }}
            >
              Исправить и продолжить
            </Button>
          </div>
        ) : null}
        
        {/* ✅ НОВЫЙ ФЛОУ: Все документы загружены */}
        {hasNewFlowDocs && allDocsProcessed && (() => {
          // Правильно считаем загруженные и пропущенные документы из documentsRequired
          const uploadedCount = documentsRequired.filter((doc: any) => {
            const docId = doc.id || doc.name;
            return uploadedDocs.includes(docId);
          }).length;
          
          const skippedCount = documentsRequired.filter((doc: any) => {
            const docId = doc.id || doc.name;
            return skippedDocs.includes(docId);
          }).length;
          
          return (
            <div style={{ textAlign: 'center', padding: '40px 0' }}>
              <Title level={4}>✅ Все документы обработаны!</Title>
              <Paragraph type="secondary">
                Загружено: {uploadedCount} из {documentsRequired.length}, пропущено: {skippedCount}
              </Paragraph>
              <Button type="primary" size="large" onClick={handleAllDocsComplete}>
                Продолжить →
              </Button>
            </div>
          );
        })()}
        
        {/* СТАРЫЙ ФЛОУ: Ожидание визарда */}
        {!hasNewFlowDocs && isWaiting && (
          <div style={{ textAlign: 'center', padding: '40px 0' }}>
            <img
              src={AiWorkingIllustration}
              alt="AI работает"
              style={{ maxWidth: 320, width: '100%', marginBottom: 24 }}
            />
            <Title level={4}>Мы собираем рекомендации для вашего случая</Title>
            <Paragraph type="secondary" style={{ maxWidth: 420, margin: '0 auto 24px' }}>
              Наш AI-ассистент анализирует ваше описание и подбирает вопросы и список документов,
              которые помогут быстро решить проблему.
            </Paragraph>
            <Space direction="vertical">
              <Skeleton.Button active size="large" style={{ width: 220 }} />
              <Skeleton.Input active size="large" style={{ width: 260 }} />
            </Space>
            <div style={{ marginTop: 32, color: '#94a3b8' }}>
              <LoadingOutlined style={{ fontSize: 28 }} spin /> Подождите несколько секунд…
            </div>
            {connectionError && (
              <div style={{ marginTop: 16 }}>
                <Text type="danger">{connectionError}</Text>
                <div>
                  <Button onClick={handleRefreshPlan} style={{ marginTop: 12 }}>
                    Попробовать снова
                  </Button>
                </div>
              </div>
            )}
          </div>
        )}

        {/* СТАРЫЙ ФЛОУ: Визард готов */}
        {!hasNewFlowDocs && !isWaiting && plan && (
          <div>
            <Title level={4} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <ThunderboltOutlined style={{ color: '#595959' }} /> План действий
            </Title>
            <Paragraph type="secondary" style={{ marginBottom: 24 }}>
              {plan.user_text || 'Ответьте на вопросы и подготовьте документы, чтобы мы могли продолжить.'}
            </Paragraph>

            {documents.length > 0 && (
              <>
              <Card
                size="small"
                style={{
                    borderRadius: 8,
                  background: '#fff',
                    border: '1px solid #d9d9d9',
                  marginBottom: 24,
                }}
                title="Документы, которые понадобятся"
              >
                <Space direction="vertical" style={{ width: '100%' }}>
                  {documents.map((doc: any) => (
                    <div
                      key={doc.id}
                      style={{
                        display: 'flex',
                        justifyContent: 'space-between',
                        alignItems: 'center',
                        gap: 8,
                        flexWrap: 'wrap',
                      }}
                    >
                      <div>
                        <Text strong>{doc.name}</Text>
                        <Paragraph type="secondary" style={{ marginBottom: 0 }}>
                          {doc.hints}
                        </Paragraph>
                      </div>
                      <Tag color={doc.required ? 'volcano' : 'geekblue'}>
                        {doc.required ? 'Обязательно' : 'Опционально'}
                      </Tag>
                    </div>
                  ))}
                </Space>
              </Card>
                
                {/* Блоки загрузки для каждого документа из плана */}
                <div style={{ marginTop: 16, marginBottom: 24 }}>
                  <Text strong style={{ fontSize: 16, marginBottom: 16, display: 'block' }}>
                    Загрузите документы
                  </Text>
                  <Space direction="vertical" style={{ width: '100%' }}>
                    {documents.map((doc: any) => {
                      const docKey = doc.id || doc.name || `doc_${Math.random()}`;
                      return (
                        <div key={docKey}>
                          {renderDocumentBlocks(docKey, [doc])}
                        </div>
                      );
                    })}
                  </Space>
                </div>
              </>
            )}

            {renderQuestions()}
          </div>
        )}
      </Card>
    </div>
  );
}
