-- Actualiza la función desplegada para registrar el pago inicial
-- atómicamente con el recibo y sus conceptos.
-- Aplicar manualmente en Supabase; este archivo no se ejecuta desde la app.
-- CREATE OR REPLACE conserva la firma, propietario y permisos de la función.
-- No modifica recibos ni abonos existentes.

CREATE OR REPLACE FUNCTION public.hce_crear_recibo_carro(
  p_recibo jsonb,
  p_conceptos jsonb
)
RETURNS jsonb
LANGUAGE plpgsql
SET search_path = pg_catalog
AS $function$
DECLARE
  concepto_item jsonb;
  siguiente_numero bigint;
  numero_recibo text;
  recibo_creado public.hce_recibos_carros%ROWTYPE;
  total_recibo numeric(12, 2);
  pago_inicial jsonb;
  tipo_pago_inicial text;
  importe_pago_inicial numeric(12, 2);
  total_abonado_inicial numeric(12, 2);
BEGIN
  IF p_recibo IS NULL OR pg_catalog.jsonb_typeof(p_recibo) <> 'object' THEN
    RAISE EXCEPTION 'Los datos del recibo no son válidos'
      USING ERRCODE = '22023';
  END IF;

  IF p_conceptos IS NULL
     OR pg_catalog.jsonb_typeof(p_conceptos) <> 'array'
     OR pg_catalog.jsonb_array_length(p_conceptos) = 0 THEN
    RAISE EXCEPTION 'Agrega al menos un concepto de cobro'
      USING ERRCODE = '22023';
  END IF;

  FOR concepto_item IN
    SELECT item.value FROM pg_catalog.jsonb_array_elements(p_conceptos) AS item(value)
  LOOP
    IF pg_catalog.jsonb_typeof(concepto_item) <> 'object'
       OR NULLIF(pg_catalog.btrim(concepto_item ->> 'concepto'), '') IS NULL
       OR pg_catalog.jsonb_typeof(concepto_item -> 'importe') <> 'number' THEN
      RAISE EXCEPTION 'Los conceptos de cobro no son válidos'
        USING ERRCODE = '22023';
    END IF;
    IF (concepto_item ->> 'importe')::numeric < 0 THEN
      RAISE EXCEPTION 'El importe de un concepto no puede ser negativo'
        USING ERRCODE = '22023';
    END IF;
  END LOOP;

  SELECT COALESCE(pg_catalog.sum(pg_catalog.round((item.value ->> 'importe')::numeric, 2)), 0)
    INTO total_recibo
    FROM pg_catalog.jsonb_array_elements(p_conceptos) AS item(value);

  pago_inicial := COALESCE(p_recibo -> 'pago_inicial', '{"tipo":"sin_pago"}'::jsonb);
  IF pg_catalog.jsonb_typeof(pago_inicial) <> 'object'
     OR pg_catalog.jsonb_typeof(pago_inicial -> 'tipo') <> 'string' THEN
    RAISE EXCEPTION 'La forma de pago inicial no es válida'
      USING ERRCODE = '22023';
  END IF;

  tipo_pago_inicial := pago_inicial ->> 'tipo';
  IF tipo_pago_inicial NOT IN ('sin_pago', 'abono_inicial', 'pago_completo') THEN
    RAISE EXCEPTION 'La forma de pago inicial no es válida'
      USING ERRCODE = '22023';
  END IF;

  total_abonado_inicial := 0;
  IF tipo_pago_inicial = 'abono_inicial' THEN
    IF pg_catalog.jsonb_typeof(pago_inicial -> 'importe') <> 'number' THEN
      RAISE EXCEPTION 'El importe del abono inicial no es válido'
        USING ERRCODE = '22023';
    END IF;
    importe_pago_inicial := pg_catalog.round((pago_inicial ->> 'importe')::numeric, 2);
    IF importe_pago_inicial <= 0 OR importe_pago_inicial > total_recibo THEN
      RAISE EXCEPTION 'El abono inicial debe ser mayor que cero y no superar el total'
        USING ERRCODE = '22023';
    END IF;
    total_abonado_inicial := importe_pago_inicial;
  ELSIF tipo_pago_inicial = 'pago_completo' AND total_recibo > 0 THEN
    total_abonado_inicial := total_recibo;
  END IF;

  PERFORM pg_catalog.pg_advisory_xact_lock(72631, 1);

  SELECT COALESCE(
           pg_catalog.max(pg_catalog.substring(numero, 5)::bigint),
           0
         ) + 1
    INTO siguiente_numero
    FROM public.hce_recibos_carros
   WHERE numero ~ '^RCC-[0-9]+$';
  numero_recibo := 'RCC-' || pg_catalog.lpad(siguiente_numero::text, 6, '0');

  INSERT INTO public.hce_recibos_carros (
    numero,
    fecha,
    remitente_id,
    destinatario_id,
    remitente_nombre,
    remitente_telefono,
    destinatario_nombre,
    destinatario_telefono,
    tipo_vehiculo,
    marca,
    modelo,
    anio,
    color,
    vin,
    puerto_destino,
    observaciones,
    total,
    total_abonado,
    saldo_pendiente,
    estado_pago
  )
  VALUES (
    numero_recibo,
    COALESCE(NULLIF(p_recibo ->> 'fecha', '')::date, CURRENT_DATE),
    NULLIF(p_recibo ->> 'remitente_id', '')::bigint,
    NULLIF(p_recibo ->> 'destinatario_id', '')::bigint,
    NULLIF(pg_catalog.btrim(p_recibo ->> 'remitente_nombre'), ''),
    NULLIF(p_recibo ->> 'remitente_telefono', ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'destinatario_nombre'), ''),
    NULLIF(p_recibo ->> 'destinatario_telefono', ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'tipo_vehiculo'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'marca'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'modelo'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'anio'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'color'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'vin'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'puerto_destino'), ''),
    NULLIF(pg_catalog.btrim(p_recibo ->> 'observaciones'), ''),
    total_recibo,
    0,
    total_recibo,
    'Pendiente'
  )
  RETURNING * INTO recibo_creado;

  INSERT INTO public.hce_recibos_carros_conceptos (
    recibo_id,
    concepto,
    importe,
    orden
  )
  SELECT
    recibo_creado.id,
    pg_catalog.btrim(item.value ->> 'concepto'),
    pg_catalog.round((item.value ->> 'importe')::numeric, 2),
    (item.ordinality - 1)::integer
    FROM pg_catalog.jsonb_array_elements(p_conceptos)
         WITH ORDINALITY AS item(value, ordinality);

  IF total_abonado_inicial > 0 THEN
    INSERT INTO public.hce_recibos_carros_pagos (
      recibo_id,
      fecha,
      importe
    )
    VALUES (
      recibo_creado.id,
      recibo_creado.fecha,
      total_abonado_inicial
    );

    UPDATE public.hce_recibos_carros
       SET total_abonado = total_abonado_inicial,
           saldo_pendiente = total_recibo - total_abonado_inicial,
           estado_pago = CASE
             WHEN total_recibo > 0 AND total_recibo - total_abonado_inicial = 0
               THEN 'Pagado'
             ELSE 'Abono parcial'
           END
     WHERE id = recibo_creado.id
     RETURNING * INTO recibo_creado;
  END IF;

  RETURN pg_catalog.to_jsonb(recibo_creado);
END;
$function$;
