'use server'
import { headers } from 'next/headers'
import { createHash } from 'crypto'
import { createClient as createSupabaseClient } from '@supabase/supabase-js'
import { buildFormSchema } from '@/lib/form-engine'
import type { Question as EngineQuestion } from '@/lib/form-engine.types'
import { validateSubmission, type SubmitAnswerEntry } from '@/lib/submit-validation'

export type SubmitResult =
  | { success: true }
  | { success: false; error: string }

export async function submitSurvey(payload: {
  surveyId: string
  answers: SubmitAnswerEntry[]
  consentOperativo: boolean
  consentMacroN1: boolean
}): Promise<SubmitResult> {
  // ip_hash: server-only, nunca en texto plano (dedup sin identidad)
  const headersList = await headers()
  const rawIp = headersList.get('x-forwarded-for')?.split(',')[0]?.trim() ?? 'unknown'
  const salt = process.env.IP_HASH_SALT ?? ''
  const ipHash = createHash('sha256').update(rawIp + salt).digest('hex')

  // Cliente con anon key — respeta RLS. NUNCA service_role (regla 9 CLAUDE.md).
  const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL ?? ''
  const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ?? ''
  const supabase = createSupabaseClient(supabaseUrl, supabaseAnonKey)

  // 1. Validación #1: survey existe y está activa
  const { data: survey, error: sErr } = await supabase
    .from('surveys')
    .select('id, org_id, status')
    .eq('id', payload.surveyId)
    .eq('status', 'live')
    .maybeSingle()

  if (sErr) return { success: false, error: 'survey_lookup_failed' }
  if (!survey) return { success: false, error: 'survey_not_found_or_not_live' }

  // 2. Carga el esquema completo de la encuesta — es contra ESTO que se valida,
  // nunca contra lo que el cliente afirma que vio.
  const { data: questionRows, error: qErr } = await supabase
    .from('questions')
    .select(
      'id, code, type, prompt, position, is_sensitive, required, hint, ' +
        'max_select, options, conditional_rules, instance_generator, instance_of'
    )
    .eq('survey_id', payload.surveyId)

  if (qErr || !questionRows) return { success: false, error: 'schema_load_failed' }

  const schema = buildFormSchema(questionRows as unknown as EngineQuestion[])

  // 3. Validaciones #2-#7 — reusa lib/form-engine.ts, no reimplementa flujo.
  const result = validateSubmission(schema, payload.answers, payload.consentOperativo)
  if (!result.ok) {
    return { success: false, error: `validation_failed: ${result.errors.join(', ')}` }
  }

  // 4. Cuasi-identificadores — códigos v3 (2.1 zona, 2.4 edad).
  // qi_sector: v3 no tiene una pregunta equivalente a "área/gerencia" de v2.
  // Se usa 2.6 (nivel organizacional) como proxy más cercano disponible —
  // decisión a confirmar con el director, no hay un mapeo exacto.
  const findDefault = (code: string): string | null => {
    const entry = payload.answers.find((e) => e.code === code && e.instanceId === 'default')
    return typeof entry?.value === 'string' ? entry.value : null
  }
  const qiZone = findDefault('2.1')
  const qiAgeBucket = findDefault('2.4')
  const qiSector = findDefault('2.6')

  // 5. Persistencia atómica vía RPC SECURITY DEFINER — ver migración
  // 20260624000001_submit_rpc.sql para el detalle de por qué RPC y no
  // INSERTs sueltos desde acá.
  const { error: rpcErr } = await supabase.rpc('rpc_submit_response', {
    p_survey_id: payload.surveyId,
    p_ip_hash: ipHash,
    p_qi_age_bucket: qiAgeBucket,
    p_qi_sector: qiSector,
    p_qi_zone: qiZone,
    p_consent_operativo: payload.consentOperativo,
    p_consent_macro_n1: payload.consentMacroN1,
    p_answers: result.rows.map((r) => ({
      question_id: r.questionId,
      instance_id: r.instanceId,
      value: r.value,
    })),
  })

  if (rpcErr) return { success: false, error: 'submit_failed' }

  return { success: true }
}
