<?php
// procesar_factura_ri.php
// Backend robusto para RI + agente de retención, con ARS/USD, NC/ND, IVA por ítem, percepciones, retenciones y flete.

include 'conexion3.php';
$conn->set_charset('utf8mb4');
$conn->query("SET NAMES utf8mb4");

function fnum($v){ return (float)str_replace(',', '.', $v ?? 0); }

// Normaliza alícuota a key string "10.50"
function ali_key($v): string {
  $n = (float)str_replace(',', '.', $v ?? 0);
  // 2 decimales, punto, sin separador miles
  return number_format($n, 2, '.', '');
}

try {
  $conn->begin_transaction();

  // ===== Encabezado =====
  $proveedor_id      = intval($_POST['proveedor_id'] ?? 0);
  $tipo_doc          = $_POST['tipo_doc'] ?? 'factura';
  $tipo_cbte_raw     = $_POST['tipo_cbte'] ?? null;
  $tipo_cbte         = ($tipo_cbte_raw === '' ? null : intval($tipo_cbte_raw));
  $numero_factura    = trim($_POST['numero_factura'] ?? '');
  $fecha_emision     = $_POST['fecha_emision'] ?? date('Y-m-d');
  $fecha_vencimiento = $_POST['fecha_vencimiento'] ?? null;

  $doc_relacionado_in = $_POST['doc_relacionado'] ?? null;
  $doc_relacionado    = ($doc_relacionado_in === '' || $doc_relacionado_in === '0' || $doc_relacionado_in === '0.00')
    ? null
    : $doc_relacionado_in;

  $moneda      = $_POST['moneda'] ?? 'ARS';
  $tipo_cambio = fnum($_POST['tipo_cambio'] ?? 1);

  $exento      = fnum($_POST['exento'] ?? 0);
  $no_gravado  = fnum($_POST['no_gravado'] ?? 0);
  $perc_iva    = fnum($_POST['perc_iva'] ?? 0);
  $perc_iibb   = fnum($_POST['perc_iibb'] ?? 0); // viene del front como Salta+Otras
  $otros_imp   = fnum($_POST['otros_imp'] ?? 0);
  $imp_total_fijo  = fnum($_POST['impuesto_total_fijo'] ?? 0);
  $desc_total_fijo = fnum($_POST['descuento_total_fijo'] ?? 0);

  // Retenciones y flete
  $ret_iibb_salta = fnum($_POST['ret_iibb_salta'] ?? 0);
  $ret_iibb_otras = fnum($_POST['ret_iibb_otras'] ?? 0);
  $flete          = fnum($_POST['flete'] ?? 0);

  // Ítems
  $producto_id    = $_POST['producto_id']    ?? [];
  $producto_code  = $_POST['producto_code']  ?? [];
  $producto_name  = $_POST['producto_name']  ?? [];
  $cantidad       = $_POST['cantidad']       ?? [];
  $precio         = $_POST['precio']         ?? [];
  $iva_item       = $_POST['impuesto']       ?? []; // % por ítem
  $desc_item      = $_POST['descuento']      ?? [];

  if (!is_array($producto_id) || count($producto_id) == 0) {
    throw new RuntimeException("No se recibieron ítems.");
  }

  // ===== Insert factura =====
  // Ojo: si tipo_cbte puede ser NULL, bind_param debe permitirlo => lo mandamos como int o null y el driver lo toma.
  $stmtF = $conn->prepare("
    INSERT INTO facturas
      (proveedor_id, numero_factura, fecha_emision, fecha_vencimiento, monto, pagado, tipo_doc, doc_relacionado, tipo_cbte)
    VALUES
      (?, ?, ?, ?, 0, 0, ?, ?, ?)
  ");
  if (!$stmtF){ throw new RuntimeException("Error preparando factura: ".$conn->error); }

  // Tipos: i s s s s s i  (tipo_cbte es int, pero si viene null lo seteamos y listo)
  // Nota: doc_relacionado es string o null; si tu columna es INT, convertí antes.
  $tipo_cbte_bind = ($tipo_cbte === null ? 0 : (int)$tipo_cbte); // si tu DB permite NULL y querés NULL real, avisame y lo hacemos con bind_param + bind_null
  $doc_rel_bind   = ($doc_relacionado === null ? null : (string)$doc_relacionado);

  $stmtF->bind_param(
    "isssssi",
    $proveedor_id,
    $numero_factura,
    $fecha_emision,
    $fecha_vencimiento,
    $tipo_doc,
    $doc_rel_bind,
    $tipo_cbte_bind
  );
  if (!$stmtF->execute()) { throw new RuntimeException("Error guardando factura: ".$stmtF->error); }
  $factura_id = $stmtF->insert_id;
  $stmtF->close();

  // ===== Items + agregación de IVA por alícuota =====
  $subtotal_items = 0.0;
  $iva_items      = 0.0;
  $descuentos_it  = 0.0;

  // ✅ clave string normalizada: "10.50" => evita truncado a 10
  $iva_map = []; // ali_key => [neto, iva]

  $cant_entregada = '0'; // varchar
  $cant_devuelta  = '0'; // varchar

  for ($i=0; $i<count($producto_id); $i++) {
    $pid = $producto_id[$i] ?? null;
    if ($pid === null || $pid === '') { continue; }

    $cant = fnum($cantidad[$i] ?? 0);
    $prec = fnum($precio[$i] ?? 0);

    // ✅ usamos key string
    $aliKey = ali_key($iva_item[$i] ?? 0);
    $ali    = (float)$aliKey; // 10.50 -> 10.5

    $desc = fnum($desc_item[$i] ?? 0);

    $pcode = substr((string)($producto_code[$i] ?? ''), 0, 20);
    $pname = substr($conn->real_escape_string((string)($producto_name[$i] ?? '')), 0, 30);

    $item_sub = $cant * $prec;
    $item_iva = $item_sub * ($ali/100.0);
    $item_tot = $item_sub + $item_iva - $desc; // (no se usa para DB, queda por si lo querés mostrar)

    $subtotal_items += $item_sub;
    $iva_items      += $item_iva;
    $descuentos_it  += $desc;

    if (!isset($iva_map[$aliKey])) { $iva_map[$aliKey] = ['neto'=>0.0,'iva'=>0.0]; }
    $iva_map[$aliKey]['neto'] += $item_sub;
    $iva_map[$aliKey]['iva']  += $item_iva;

    // Insert item
    $stmtI = $conn->prepare("
      INSERT INTO factura_items
        (factura_id, producto_id, cantidad, precio_unitario, impuesto, descuento, subtotal,
         cantidad_entregada, factura_numero, producto_name, sup_id, producto_code, cantidad_devuelta)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    ");
    if (!$stmtI) { throw new RuntimeException("Error prepare items: ".$conn->error); }

    $stmtI->bind_param(
      "iidddddsssiss",
      $factura_id, $pid, $cant, $prec, $ali, $desc, $item_sub,
      $cant_entregada, $numero_factura, $pname, $proveedor_id, $pcode, $cant_devuelta
    );
    if (!$stmtI->execute()) { throw new RuntimeException("Error al insertar item: ".$stmtI->error); }
    $stmtI->close();
  }

  // ===== Totales front y ajustes backend =====
  $total_factura   = fnum($_POST['total_factura'] ?? $subtotal_items);
  $total_impuesto  = fnum($_POST['total_impuesto'] ?? ($iva_items + $imp_total_fijo));
  $total_descuento = fnum($_POST['total_descuento'] ?? ($descuentos_it + $desc_total_fijo));

  // Flete + retenciones (retenciones restan)
  $otros_imp_total = $otros_imp + $flete - ($ret_iibb_salta + $ret_iibb_otras);

  $total_factura_final = fnum($_POST['total_factura_final'] ?? (
    $subtotal_items + $iva_items + $imp_total_fijo
    - $descuentos_it - $desc_total_fijo
    + $perc_iva + $perc_iibb
    + $otros_imp_total
  ));

  // NC => negativo en monto
  if ($tipo_doc === 'nc') { $total_factura_final *= -1; }

  // ===== Guardar IVA por alícuota (conversión a ARS) =====
  $tc = $tipo_cambio > 0 ? $tipo_cambio : 1;

  if (!empty($iva_map)) {
    $stmtD = $conn->prepare("
      INSERT INTO factura_iva_detalle (factura_id, alicuota, neto, iva, neto_ars, iva_ars)
      VALUES (?, ?, ?, ?, ?, ?)
    ");
    if (!$stmtD) { throw new RuntimeException("Error prepare iva detalle: ".$conn->error); }

    foreach ($iva_map as $aliKey => $vals) {
      $ali = (float)$aliKey;

      $n = round($vals['neto'], 2);
      $v = round($vals['iva'], 2);
      $n_ars = round($n * $tc, 2);
      $v_ars = round($v * $tc, 2);

      $stmtD->bind_param("iddddd", $factura_id, $ali, $n, $v, $n_ars, $v_ars);
      if (!$stmtD->execute()) { throw new RuntimeException("Error insert iva detalle: ".$stmtD->error); }
    }
    $stmtD->close();
  }

  // ===== Actualizar monto en facturas =====
  $stmtU = $conn->prepare("UPDATE facturas SET monto = ? WHERE id = ?");
  if (!$stmtU) { throw new RuntimeException("Error prepare update monto: ".$conn->error); }
  $stmtU->bind_param("di", $total_factura_final, $factura_id);
  if (!$stmtU->execute()) { throw new RuntimeException("Error update monto: ".$stmtU->error); }
  $stmtU->close();

  // ===== Guardar totales en factura_price (moneda y ARS) =====
  $subtotal_ars   = round($subtotal_items * $tc, 2);
  $impuestos_ars  = round($total_impuesto * $tc, 2);
  $descuentos_ars = round($total_descuento * $tc, 2);
  $total_ars      = round($total_factura_final * $tc, 2);

  $exento_ars     = round($exento * $tc, 2);
  $no_gravado_ars = round($no_gravado * $tc, 2);
  $perc_iva_ars   = round($perc_iva * $tc, 2);
  $perc_iibb_ars  = round($perc_iibb * $tc, 2);
  $otros_imp_ars  = round($otros_imp_total * $tc, 2);

  $stmtP = $conn->prepare("
    INSERT INTO factura_price
      (factura_id, subtotal, impuestos, descuentos, total,
       exento, no_gravado, perc_iva, perc_iibb, otros_imp,
       moneda, tipo_cambio,
       subtotal_ars, impuestos_ars, descuentos_ars, total_ars,
       exento_ars, no_gravado_ars, perc_iva_ars, perc_iibb_ars, otros_imp_ars)
    VALUES
      (?,?,?,?,?,
       ?,?,?,?,?,
       ?,?,
       ?,?,?,?,
       ?,?,?,?,?)
  ");
  if (!$stmtP) { throw new RuntimeException("Error prepare totales: ".$conn->error); }

  $stmtP->bind_param(
    "idddddddddsdddddddddd",
    $factura_id, $subtotal_items, $total_impuesto, $total_descuento, $total_factura_final,
    $exento, $no_gravado, $perc_iva, $perc_iibb, $otros_imp_total,
    $moneda, $tipo_cambio,
    $subtotal_ars, $impuestos_ars, $descuentos_ars, $total_ars,
    $exento_ars, $no_gravado_ars, $perc_iva_ars, $perc_iibb_ars, $otros_imp_ars
  );
  if (!$stmtP->execute()) { throw new RuntimeException("Error insert totales: ".$stmtP->error); }
  $stmtP->close();

  $conn->commit();

  echo "<script>alert('Documento registrado correctamente'); location.href='cuenta_proveedor.php?proveedor_id={$proveedor_id}';</script>";
  exit;

} catch (Throwable $e) {
  $conn->rollback();
  http_response_code(500);
  echo "<pre style='padding:12px;background:#fff3cd;border:1px solid #ffeeba'>ERROR:\n"
    . htmlspecialchars($e->getMessage()) . "</pre>";
  exit;
}
