-- ============================================================================
-- SQL для сохранения claim при пропуске документа (document skip) - НОВЫЙ ФЛОУ
-- ============================================================================
-- Проблема: При пропуске документа нужно обновить documents_skipped и current_doc_index
-- Решение: Добавляем документ в documents_skipped, обновляем current_doc_index и status_code
-- ============================================================================

WITH partial AS (
  SELECT 
    $1::jsonb AS p, 
    $2::text AS claim_id_str
),

existing_claim AS (
  SELECT 
    id,
    session_token,
    unified_id,
    contact_id,
    phone,
    payload,
    status_code,
    created_at
  FROM clpr_claims
  WHERE id = (SELECT claim_id_str::uuid FROM partial)
     OR payload->>'claim_id' = (SELECT claim_id_str FROM partial)
  ORDER BY 
    CASE WHEN id = (SELECT claim_id_str::uuid FROM partial) THEN 1 ELSE 2 END,
    updated_at DESC
  LIMIT 1
),

-- Парсим информацию о пропущенном документе
skipped_document_info AS (
  SELECT 
    COALESCE(
      partial.p->>'document_type',
      partial.p->'body'->>'document_type',
      partial.p->'edit_fields_raw'->'body'->>'document_type',
      partial.p->'edit_fields_parsed'->'body'->>'document_type'
    ) AS document_type,
    COALESCE(
      partial.p->>'document_name',
      partial.p->'body'->>'document_name',
      partial.p->'edit_fields_raw'->'body'->>'document_name',
      partial.p->'edit_fields_parsed'->'body'->>'document_name'
    ) AS document_name,
    COALESCE(
      (partial.p->>'group_index')::int,
      (partial.p->'body'->>'group_index')::int,
      (partial.p->'edit_fields_raw'->'body'->>'group_index')::int,
      (partial.p->'edit_fields_parsed'->'body'->>'group_index')::int,
      NULL
    ) AS group_index
  FROM partial
),

-- Парсим documents_required (или берём из БД)
documents_required_parsed AS (
  SELECT 
    CASE 
      WHEN partial.p->'documents_required' IS NOT NULL 
        AND jsonb_typeof(partial.p->'documents_required') = 'array'
        THEN partial.p->'documents_required'
      WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'documents_required' IS NOT NULL)
        THEN (SELECT payload->'documents_required' FROM existing_claim)
      ELSE '[]'::jsonb
    END AS documents_required
  FROM partial
),

-- Парсим documents_uploaded (или берём из БД)
documents_uploaded_parsed AS (
  SELECT 
    CASE 
      WHEN partial.p->'documents_uploaded' IS NOT NULL 
        AND jsonb_typeof(partial.p->'documents_uploaded') = 'array'
        THEN partial.p->'documents_uploaded'
      WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'documents_uploaded' IS NOT NULL)
        THEN (SELECT payload->'documents_uploaded' FROM existing_claim)
      ELSE '[]'::jsonb
    END AS documents_uploaded
  FROM partial
),

-- Парсим documents_skipped (или берём из БД) и ДОБАВЛЯЕМ/ОБНОВЛЯЕМ новый пропущенный документ
documents_skipped_parsed AS (
  SELECT 
    CASE 
      -- Если документ уже есть в списке пропущенных - ОБНОВЛЯЕМ его (добавляем group_index, если его нет)
      WHEN EXISTS (
        SELECT 1 
        FROM existing_claim 
        WHERE payload->'documents_skipped' @> jsonb_build_array(
          jsonb_build_object(
            'id', (SELECT document_type FROM skipped_document_info)
          )
        )
      )
        THEN (
          -- Удаляем старую запись и добавляем новую с group_index
          SELECT jsonb_agg(
            CASE 
              WHEN doc->>'id' = (SELECT document_type FROM skipped_document_info)
                THEN jsonb_build_object(
                  'id', (SELECT document_type FROM skipped_document_info),
                  'name', COALESCE((SELECT document_name FROM skipped_document_info), (SELECT document_type FROM skipped_document_info)),
                  'group_index', (SELECT group_index FROM skipped_document_info),
                  'skipped_at', COALESCE(doc->>'skipped_at', now()::text)
                )
              ELSE doc
            END
          )
          FROM existing_claim,
          jsonb_array_elements(payload->'documents_skipped') AS doc
        )
      -- Добавляем новый пропущенный документ
      WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'documents_skipped' IS NOT NULL)
        THEN (
          SELECT payload->'documents_skipped' || jsonb_build_array(
            jsonb_build_object(
              'id', (SELECT document_type FROM skipped_document_info),
              'name', COALESCE((SELECT document_name FROM skipped_document_info), (SELECT document_type FROM skipped_document_info)),
              'group_index', (SELECT group_index FROM skipped_document_info),
              'skipped_at', now()::text
            )
          )
          FROM existing_claim
        )
      -- Создаём новый массив с пропущенным документом
      ELSE jsonb_build_array(
        jsonb_build_object(
          'id', (SELECT document_type FROM skipped_document_info),
          'name', COALESCE((SELECT document_name FROM skipped_document_info), (SELECT document_type FROM skipped_document_info)),
          'group_index', (SELECT group_index FROM skipped_document_info),
          'skipped_at', now()::text
        )
      )
    END AS documents_skipped
  FROM partial
),

-- Парсим current_doc_index и ОБНОВЛЯЕМ его (увеличиваем на 1 или находим следующий непропущенный)
current_doc_index_parsed AS (
  SELECT 
    CASE 
      -- Если передан group_index - используем его + 1
      WHEN (SELECT group_index FROM skipped_document_info) IS NOT NULL
        THEN (SELECT group_index FROM skipped_document_info) + 1
      -- Иначе берём из payload и увеличиваем на 1
      WHEN partial.p->'current_doc_index' IS NOT NULL 
        THEN (partial.p->'current_doc_index')::int + 1
      WHEN EXISTS (SELECT 1 FROM existing_claim WHERE payload->'current_doc_index' IS NOT NULL)
        THEN (SELECT (payload->'current_doc_index')::int FROM existing_claim) + 1
      ELSE 1
    END AS current_doc_index
  FROM partial
),

-- Определяем правильный статус на основе прогресса документов
status_code_resolved AS (
  SELECT 
    CASE
      -- Если есть documents_required - новый флоу
      WHEN (SELECT jsonb_array_length(documents_required) FROM documents_required_parsed) > 0
        THEN CASE
          -- Все документы загружены или пропущены
          WHEN (SELECT jsonb_array_length(documents_uploaded) FROM documents_uploaded_parsed) + 
               (SELECT jsonb_array_length(documents_skipped) FROM documents_skipped_parsed) >= 
               (SELECT jsonb_array_length(documents_required) FROM documents_required_parsed)
            THEN 'draft_docs_complete'
          -- Документы обрабатываются (есть загруженные или пропущенные)
          WHEN (SELECT jsonb_array_length(documents_uploaded) FROM documents_uploaded_parsed) > 0
            OR (SELECT jsonb_array_length(documents_skipped) FROM documents_skipped_parsed) > 0
            THEN 'draft_docs_progress'
          -- Только описание
          ELSE 'draft_new'
        END
      -- Сохраняем существующий статус, если он новый
      WHEN EXISTS (SELECT 1 FROM existing_claim 
                   WHERE status_code IN ('draft_new', 'draft_docs_progress', 'draft_docs_complete', 'draft_claim_ready'))
        THEN (SELECT status_code FROM existing_claim)
      -- По умолчанию
      ELSE 'draft'
    END AS status_code
  FROM partial
),

-- UPSERT claim
claim_upsert AS (
  INSERT INTO clpr_claims (
    id,
    session_token,
    unified_id,
    contact_id,
    phone,
    channel,
    type_code,
    status_code,
    payload,
    created_at,
    updated_at,
    expires_at
  )
  SELECT 
    COALESCE((SELECT id FROM existing_claim), partial.claim_id_str::uuid),
    COALESCE(
      partial.p->>'session_id',
      partial.p->'body'->>'session_id',
      partial.p->'edit_fields_parsed'->'body'->>'session_id',
      partial.p->'edit_fields_raw'->'body'->>'session_id',
      (SELECT payload->>'session_id' FROM existing_claim),
      'sess-unknown'
    ),
    COALESCE(
      partial.p->>'unified_id',
      partial.p->'body'->>'unified_id',
      partial.p->'edit_fields_parsed'->'body'->>'unified_id',
      partial.p->'edit_fields_raw'->'body'->>'unified_id',
      (SELECT unified_id FROM existing_claim)
    ),
    COALESCE(
      partial.p->>'contact_id',
      partial.p->'body'->>'contact_id',
      partial.p->'edit_fields_parsed'->'body'->>'contact_id',
      partial.p->'edit_fields_raw'->'body'->>'contact_id',
      (SELECT contact_id FROM existing_claim)
    ),
    COALESCE(
      partial.p->>'phone',
      partial.p->'body'->>'phone',
      partial.p->'edit_fields_parsed'->'body'->>'phone',
      partial.p->'edit_fields_raw'->'body'->>'phone',
      (SELECT phone FROM existing_claim)
    ),
    'web_form',
    COALESCE(partial.p->>'type_code', 'consumer'),
    (SELECT status_code FROM status_code_resolved),
    jsonb_build_object(
      'claim_id', partial.claim_id_str,
      -- Сохраняем существующие поля из payload
      'problem_description', COALESCE(
        partial.p->>'problem_description',
        (SELECT payload->>'problem_description' FROM existing_claim)
      ),
      'answers', COALESCE(
        partial.p->'answers',
        (SELECT payload->'answers' FROM existing_claim),
        '{}'::jsonb
      ),
      'wizard_plan', COALESCE(
        partial.p->'wizard_plan',
        (SELECT payload->'wizard_plan' FROM existing_claim)
      ),
      -- ✅ Сохраняем documents_meta (если есть)
      'documents_meta', COALESCE(
        partial.p->'documents_meta',
        (SELECT payload->'documents_meta' FROM existing_claim),
        '[]'::jsonb
      ),
      -- ✅ НОВЫЙ ФЛОУ: Обновляем documents_required, documents_uploaded, documents_skipped, current_doc_index
      'documents_required', (SELECT documents_required FROM documents_required_parsed),
      'documents_uploaded', (SELECT documents_uploaded FROM documents_uploaded_parsed),
      'documents_skipped', (SELECT documents_skipped FROM documents_skipped_parsed),
      'current_doc_index', (SELECT current_doc_index FROM current_doc_index_parsed),
      'phone', COALESCE(
        partial.p->>'phone',
        (SELECT payload->>'phone' FROM existing_claim)
      ),
      'email', COALESCE(
        partial.p->>'email',
        (SELECT payload->>'email' FROM existing_claim)
      )
    ),
    COALESCE((SELECT created_at FROM existing_claim), now()),
    now(),
    now() + interval '14 days'
  FROM partial
  ON CONFLICT (id) DO UPDATE SET
    session_token = COALESCE(EXCLUDED.session_token, clpr_claims.session_token),
    unified_id = COALESCE(EXCLUDED.unified_id, clpr_claims.unified_id),
    contact_id = COALESCE(EXCLUDED.contact_id, clpr_claims.contact_id),
    phone = COALESCE(EXCLUDED.phone, clpr_claims.phone),
    -- ✅ Обновляем status_code на основе прогресса документов
    status_code = (SELECT status_code FROM status_code_resolved),
    -- ✅ Объединяем payload правильно: аккуратно обновляем критичные поля
    payload = jsonb_set(
      jsonb_set(
        jsonb_set(
          jsonb_set(
            -- Сначала берём существующий payload и объединяем с новым (без критичных полей)
            COALESCE(clpr_claims.payload, '{}'::jsonb) || 
            (EXCLUDED.payload - 'documents_required' - 'documents_uploaded' - 'documents_skipped' - 'current_doc_index'),
            '{documents_required}',
            COALESCE(
              EXCLUDED.payload->'documents_required',
              clpr_claims.payload->'documents_required',
              '[]'::jsonb
            ),
            true
          ),
          '{documents_uploaded}',
          COALESCE(
            EXCLUDED.payload->'documents_uploaded',
            clpr_claims.payload->'documents_uploaded',
            '[]'::jsonb
          ),
          true
        ),
        '{documents_skipped}',
        -- ✅ ОБЪЕДИНЯЕМ documents_skipped (добавляем новый пропущенный документ или ОБНОВЛЯЕМ существующий)
        CASE
          -- Если новый документ уже есть в существующем списке - ОБНОВЛЯЕМ его (добавляем group_index)
          WHEN clpr_claims.payload->'documents_skipped' @> jsonb_build_array(
            jsonb_build_object(
              'id', (SELECT document_type FROM skipped_document_info)
            )
          )
            THEN (
              -- Обновляем существующую запись, добавляя group_index
              SELECT jsonb_agg(
                CASE 
                  WHEN doc->>'id' = (SELECT document_type FROM skipped_document_info)
                    THEN jsonb_build_object(
                      'id', (SELECT document_type FROM skipped_document_info),
                      'name', COALESCE((SELECT document_name FROM skipped_document_info), (SELECT document_type FROM skipped_document_info)),
                      'group_index', (SELECT group_index FROM skipped_document_info),
                      'skipped_at', COALESCE(doc->>'skipped_at', now()::text)
                    )
                  ELSE doc
                END
              )
              FROM jsonb_array_elements(clpr_claims.payload->'documents_skipped') AS doc
            )
          -- Добавляем новый пропущенный документ
          ELSE COALESCE(clpr_claims.payload->'documents_skipped', '[]'::jsonb) || jsonb_build_array(
            jsonb_build_object(
              'id', (SELECT document_type FROM skipped_document_info),
              'name', COALESCE((SELECT document_name FROM skipped_document_info), (SELECT document_type FROM skipped_document_info)),
              'group_index', (SELECT group_index FROM skipped_document_info),
              'skipped_at', now()::text
            )
          )
        END,
        true
      ),
      '{current_doc_index}',
      COALESCE(
        EXCLUDED.payload->'current_doc_index',
        -- Если не передан, увеличиваем существующий на 1
        CASE
          WHEN clpr_claims.payload->'current_doc_index' IS NOT NULL
            THEN to_jsonb((clpr_claims.payload->'current_doc_index')::int + 1)
          ELSE to_jsonb(1)
        END
      ),
      true
    ),
    updated_at = now(),
    expires_at = now() + interval '14 days'
  RETURNING id, status_code, payload, unified_id, contact_id, phone, session_token
)

-- Возвращаем результат
SELECT
  jsonb_build_object(
    'claim_id', cu.id::text,
    'claim_id_str', (cu.payload->>'claim_id'),
    'status_code', cu.status_code,
    'unified_id', cu.unified_id,
    'contact_id', cu.contact_id,
    'phone', cu.phone,
    'session_token', cu.session_token,
    'payload', cu.payload,
    'documents_skipped', cu.payload->'documents_skipped',
    'current_doc_index', cu.payload->'current_doc_index'
  ) AS claim
FROM claim_upsert cu;

