<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

require_once __DIR__ . '/_common.php';
// contador_require_login();

$desde  = date_or_null($_GET['desde'] ?? '') ?: date('Y-m-01');
$hasta  = date_or_null($_GET['hasta'] ?? '') ?: date('Y-m-t');
$tipo   = trim($_GET['tipo'] ?? ''); // opcional: factura / nc / z / etc
$export = trim($_GET['export'] ?? ''); // '', 'csv', 'arca'

$pdo = db();

/**
 * 1) ARCA ZIP antes de imprimir HTML/CSV
 */
if ($export === 'arca') {
  try {
    export_arca_zip_compras($pdo, $desde, $hasta, $tipo);
  } catch (Throwable $e) {
    http_response_code(500);
    echo "<pre style='padding:12px;background:#fff3cd;border:1px solid #ffeeba'>ERROR ARCA ZIP:\n"
      . htmlspecialchars($e->getMessage()) . "</pre>";
  }
  exit;
}

/**
 * 2) Query principal
 */
$wh = ["f.fecha_emision BETWEEN :desde AND :hasta"];
$params = [':desde' => $desde, ':hasta' => $hasta];

if ($tipo !== '') {
  $wh[] = "f.tipo_doc = :tipo";
  $params[':tipo'] = $tipo;
} else {
  // por defecto excluimos "z"
  $wh[] = "f.tipo_doc <> 'z'";
}

list($where, $params) = build_query_range($wh, $params);

$sql = "
SELECT
  f.id,
  f.fecha_emision,
  f.tipo_doc,
  f.tipo_cbte,
  f.numero_factura,
  s.sup_name AS proveedor,
  s.sup_cuit AS cuit,
  fp.moneda,
  fp.tipo_cambio,
  fp.exento_ars,
  fp.no_gravado_ars,
  fp.perc_iva_ars,
  fp.perc_iibb_ars,
  fp.otros_imp_ars,
  fp.total_ars,

  -- Neto gravado e IVA total (ARS) desde detalle por alícuota:
  COALESCE(SUM(CASE WHEN fid.alicuota > 0 THEN fid.neto_ars ELSE 0 END),0) AS neto_gravado_ars,
  COALESCE(SUM(CASE WHEN fid.alicuota > 0 THEN fid.iva_ars  ELSE 0 END),0) AS iva_ars,

  -- IVA discriminado (ARS)
  COALESCE(SUM(CASE WHEN fid.alicuota = 21.00 THEN fid.iva_ars ELSE 0 END),0) AS iva21_ars,
  COALESCE(SUM(CASE WHEN fid.alicuota = 10.50 THEN fid.iva_ars ELSE 0 END),0) AS iva105_ars,
  COALESCE(SUM(CASE WHEN fid.alicuota = 27.00 THEN fid.iva_ars ELSE 0 END),0) AS iva27_ars,

  COALESCE(SUM(CASE WHEN fid.alicuota = 0.00 THEN fid.neto_ars ELSE 0 END),0) AS neto0_ars
FROM facturas f
LEFT JOIN suppliers s ON s.sup_id = f.proveedor_id
LEFT JOIN factura_price fp ON fp.factura_id = f.id
LEFT JOIN factura_iva_detalle fid ON fid.factura_id = f.id
$where
GROUP BY f.id
ORDER BY f.fecha_emision ASC, f.id ASC
";

try {
  $stmt = $pdo->prepare($sql);
  $stmt->execute($params);
  $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
  http_response_code(500);
  echo "<pre style='padding:12px;background:#fff3cd;border:1px solid #ffeeba'>ERROR SQL/PHP:\n"
    . htmlspecialchars($e->getMessage()) . "\n\nSQL:\n" . htmlspecialchars($sql) . "</pre>";
  exit;
}

/**
 * Helper: define signo (NC => -1)
 */
function is_nc_compra(array $r): bool {
  $td = strtolower(trim((string)($r['tipo_doc'] ?? '')));
  // soporta varias formas
  $byTipoDoc = in_array($td, ['nc','nota_credito','nota crédito','nota_credito_compra','nota-de-credito','nota de credito','nota de crédito'], true);

  // tipos AFIP comunes de NOTA DE CRÉDITO: A=3, B=8, C=13
  $tc = (int)($r['tipo_cbte'] ?? 0);
  $byTipoCbte = in_array($tc, [3,8,13], true);

  return $byTipoDoc || $byTipoCbte;
}

/**
 * 3) Totales (aplicando signo)
 */
$sum = [
  'neto_gravado' => 0, 'iva' => 0, 'exento' => 0, 'no_gravado' => 0,
  'perc_iva' => 0, 'perc_iibb' => 0, 'otros' => 0, 'total' => 0
];

foreach ($rows as $r) {
  $sign = is_nc_compra($r) ? -1 : 1;

  $sum['neto_gravado'] += $sign * (float)$r['neto_gravado_ars'];
  $sum['iva']          += $sign * (float)$r['iva_ars'];
  $sum['exento']       += $sign * (float)$r['exento_ars'];
  $sum['no_gravado']   += $sign * (float)$r['no_gravado_ars'];
  $sum['perc_iva']     += $sign * (float)$r['perc_iva_ars'];
  $sum['perc_iibb']    += $sign * (float)$r['perc_iibb_ars'];
  $sum['otros']        += $sign * (float)$r['otros_imp_ars'];
  $sum['total']        += $sign * (float)$r['total_ars'];
}

/**
 * 4) Export CSV (con signo)
 */
if ($export === 'csv') {
  header('Content-Type: text/csv; charset=UTF-8');
  header('Content-Disposition: attachment; filename="libro_iva_compras_'.$desde.'_a_'.$hasta.'.csv"');

  $out = fopen('php://output', 'w');
  // BOM UTF-8 para Excel
  fprintf($out, chr(0xEF).chr(0xBB).chr(0xBF));

  fputcsv($out, [
    'Fecha', 'Proveedor', 'CUIT', 'Tipo Doc', 'Tipo Cbte', 'Nro',
    'Neto Gravado (ARS)', 'IVA (ARS)', 'IVA 21', 'IVA 10.5', 'IVA 27',
    'Exento', 'No Gravado', 'Perc IVA', 'Perc IIBB', 'Otros', 'Total (ARS)',
    'SIGNO'
  ], ';');

  foreach ($rows as $r) {
    $sign = is_nc_compra($r) ? -1 : 1;

    fputcsv($out, [
      $r['fecha_emision'],
      $r['proveedor'],
      $r['cuit'],
      $r['tipo_doc'],
      $r['tipo_cbte'],
      $r['numero_factura'],
      numcsv($sign * (float)$r['neto_gravado_ars']),
      numcsv($sign * (float)$r['iva_ars']),
      numcsv($sign * (float)$r['iva21_ars']),
      numcsv($sign * (float)$r['iva105_ars']),
      numcsv($sign * (float)$r['iva27_ars']),
      numcsv($sign * (float)$r['exento_ars']),
      numcsv($sign * (float)$r['no_gravado_ars']),
      numcsv($sign * (float)$r['perc_iva_ars']),
      numcsv($sign * (float)$r['perc_iibb_ars']),
      numcsv($sign * (float)$r['otros_imp_ars']),
      numcsv($sign * (float)$r['total_ars']),
      ($sign < 0 ? '-1' : '1')
    ], ';');
  }

  fclose($out);
  exit;
}

/**
 * 5) HTML
 */
$title = "Libro IVA Compras";
ob_start();
?>

<style>
/* ============================================================
   ✅ AJUSTE MANUAL DE TAMAÑOS (tocás SOLO acá)
   ============================================================ */
:root{
  --fs-base: 13.5px;  /* general */
  --fs-table: 13px;   /* tabla (subí a 13.5 / 14 si querés) */
}

.conta-wrap { font-size: var(--fs-base); }

.conta-wrap .form-label { font-size: calc(var(--fs-base) - 1.2px); margin-bottom:.25rem; color:#1f3b64; font-weight:700; }
.conta-wrap .form-control, 
.conta-wrap .form-select { font-size: var(--fs-base); padding:.40rem .55rem; border-radius:.65rem; }

.conta-wrap .card { border-radius: 14px; }
.conta-wrap .btn { border-radius: .70rem; }

.btn-corp{
  background:#0b5ed7;
  border-color:#0b5ed7;
  color:#fff;
  box-shadow: 0 6px 18px rgba(13,110,253,.12);
}
.btn-corp:hover{ filter: brightness(.97); color:#fff; }

.btn-soft{
  border-color: rgba(13,110,253,.35);
  color:#0b5ed7;
  background: rgba(13,110,253,.07);
}
.btn-soft:hover{ background: rgba(13,110,253,.11); color:#0b5ed7; }

.kpi { padding:.75rem .9rem; }
.kpi small { display:block; font-size: calc(var(--fs-base) - 2.3px); color:#5c6f91; letter-spacing:.2px; }
.kpi .kpi-val { font-size: calc(var(--fs-base) + 2.0px); font-weight: 800; color:#0b2f5b; }

.conta-table{ font-size: var(--fs-table); }
.conta-table th{
  font-size: calc(var(--fs-table) - 1.0px);
  color:#264a7a;
  letter-spacing:.2px;
  white-space: nowrap;
}
.conta-table td{ white-space: nowrap; }
.conta-table thead.table-light{ background:#f2f7ff; }
.conta-table tbody tr:hover{ background: rgba(13,110,253,.04); }
.conta-table.table-sm > :not(caption) > * > * { padding:.36rem .45rem; }

.text-mono{
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

/* NC visual */
.badge-nc{
  background: rgba(220,53,69,.12);
  color:#b02a37;
  border:1px solid rgba(220,53,69,.25);
  font-weight:800;
}
.neg{ color:#b02a37; font-weight:700; }
</style>

<div class="conta-wrap">

<div class="card shadow-sm border-0 mb-3">
  <div class="card-body">
    <form class="row g-2 align-items-end" method="get">
      <div class="col-12 col-md-3">
        <label class="form-label">Desde</label>
        <input type="date" name="desde" value="<?= h($desde) ?>" class="form-control">
      </div>
      <div class="col-12 col-md-3">
        <label class="form-label">Hasta</label>
        <input type="date" name="hasta" value="<?= h($hasta) ?>" class="form-control">
      </div>
      <div class="col-12 col-md-3">
        <label class="form-label">Tipo doc (opcional)</label>
        <input type="text" name="tipo" value="<?= h($tipo) ?>" class="form-control" placeholder="factura / nc / z / ...">
      </div>
      <div class="col-12 col-md-3 d-flex gap-2">
        <button class="btn btn-corp w-100" type="submit">Filtrar</button>

        <a class="btn btn-soft w-100"
           href="?desde=<?= h($desde) ?>&hasta=<?= h($hasta) ?>&tipo=<?= urlencode($tipo) ?>&export=arca">
          ARCA
        </a>

        <a class="btn btn-outline-secondary w-100"
           href="?desde=<?= h($desde) ?>&hasta=<?= h($hasta) ?>&tipo=<?= urlencode($tipo) ?>&export=csv">
          CSV
        </a>
      </div>
    </form>
  </div>
</div>

<div class="row g-3 mb-3">
  <div class="col-6 col-lg-3">
    <div class="card border-0 shadow-sm">
      <div class="card-body kpi">
        <small>Neto gravado</small>
        <div class="kpi-val">$ <?= money($sum['neto_gravado']) ?></div>
      </div>
    </div>
  </div>
  <div class="col-6 col-lg-3">
    <div class="card border-0 shadow-sm">
      <div class="card-body kpi">
        <small>IVA</small>
        <div class="kpi-val">$ <?= money($sum['iva']) ?></div>
      </div>
    </div>
  </div>
  <div class="col-6 col-lg-3">
    <div class="card border-0 shadow-sm">
      <div class="card-body kpi">
        <small>Percepciones</small>
        <div class="kpi-val">$ <?= money($sum['perc_iva'] + $sum['perc_iibb']) ?></div>
      </div>
    </div>
  </div>
  <div class="col-6 col-lg-3">
    <div class="card border-0 shadow-sm">
      <div class="card-body kpi">
        <small>Total</small>
        <div class="kpi-val">$ <?= money($sum['total']) ?></div>
      </div>
    </div>
  </div>
</div>

<div class="card shadow-sm border-0">
  <div class="card-body">
    <div class="table-responsive">
      <table class="table table-sm table-hover align-middle conta-table">
        <thead class="table-light">
          <tr>
            <th>Fecha</th>
            <th>Proveedor</th>
            <th>CUIT</th>
            <th>Tipo</th>
            <th>Cbte</th>
            <th>Número</th>
            <th class="text-end">Neto</th>
            <th class="text-end">IVA</th>
            <th class="text-end">IVA21</th>
            <th class="text-end">IVA10.5</th>
            <th class="text-end">IVA27</th>
            <th class="text-end">Exento</th>
            <th class="text-end">No grav.</th>
            <th class="text-end">Perc IVA</th>
            <th class="text-end">Perc IIBB</th>
            <th class="text-end">Otros</th>
            <th class="text-end">Total</th>
          </tr>
        </thead>
        <tbody>
          <?php if (!$rows): ?>
            <tr><td colspan="17" class="text-center text-muted py-4">Sin resultados.</td></tr>
          <?php endif; ?>

          <?php foreach ($rows as $r):
            $isNC = is_nc_compra($r);
            $sign = $isNC ? -1 : 1;

            $neto = $sign * (float)$r['neto_gravado_ars'];
            $iva  = $sign * (float)$r['iva_ars'];
            $iva21  = $sign * (float)$r['iva21_ars'];
            $iva105 = $sign * (float)$r['iva105_ars'];
            $iva27  = $sign * (float)$r['iva27_ars'];

            $exento = $sign * (float)$r['exento_ars'];
            $nog    = $sign * (float)$r['no_gravado_ars'];
            $piva   = $sign * (float)$r['perc_iva_ars'];
            $piibb  = $sign * (float)$r['perc_iibb_ars'];
            $otros  = $sign * (float)$r['otros_imp_ars'];
            $total  = $sign * (float)$r['total_ars'];
          ?>
            <tr>
              <td><?= h($r['fecha_emision']) ?></td>
              <td>
                <?= h($r['proveedor']) ?>
                <?php if ($isNC): ?>
                  <span class="badge badge-nc ms-1">NC</span>
                <?php endif; ?>
              </td>
              <td class="text-mono"><?= h($r['cuit']) ?></td>
              <td><?= h($r['tipo_doc']) ?></td>
              <td><?= h($r['tipo_cbte']) ?></td>
              <td class="text-mono"><?= h($r['numero_factura']) ?></td>

              <td class="text-end <?= ($neto<0?'neg':'') ?>">$ <?= money($neto) ?></td>
              <td class="text-end <?= ($iva<0?'neg':'') ?>">$ <?= money($iva) ?></td>
              <td class="text-end <?= ($iva21<0?'neg':'') ?>">$ <?= money($iva21) ?></td>
              <td class="text-end <?= ($iva105<0?'neg':'') ?>">$ <?= money($iva105) ?></td>
              <td class="text-end <?= ($iva27<0?'neg':'') ?>">$ <?= money($iva27) ?></td>

              <td class="text-end <?= ($exento<0?'neg':'') ?>">$ <?= money($exento) ?></td>
              <td class="text-end <?= ($nog<0?'neg':'') ?>">$ <?= money($nog) ?></td>
              <td class="text-end <?= ($piva<0?'neg':'') ?>">$ <?= money($piva) ?></td>
              <td class="text-end <?= ($piibb<0?'neg':'') ?>">$ <?= money($piibb) ?></td>
              <td class="text-end <?= ($otros<0?'neg':'') ?>">$ <?= money($otros) ?></td>
              <td class="text-end fw-semibold <?= ($total<0?'neg':'') ?>">$ <?= money($total) ?></td>
            </tr>
          <?php endforeach; ?>
        </tbody>

        <tfoot class="table-light">
          <tr>
            <th colspan="6" class="text-end">Totales</th>
            <th class="text-end">$ <?= money($sum['neto_gravado']) ?></th>
            <th class="text-end">$ <?= money($sum['iva']) ?></th>
            <th colspan="3"></th>
            <th class="text-end">$ <?= money($sum['exento']) ?></th>
            <th class="text-end">$ <?= money($sum['no_gravado']) ?></th>
            <th class="text-end">$ <?= money($sum['perc_iva']) ?></th>
            <th class="text-end">$ <?= money($sum['perc_iibb']) ?></th>
            <th class="text-end">$ <?= money($sum['otros']) ?></th>
            <th class="text-end">$ <?= money($sum['total']) ?></th>
          </tr>
        </tfoot>
      </table>
    </div>

    <div class="small text-muted">
      ✅ Las Notas de Crédito (NC) se muestran y computan en negativo.
      • Ajuste tamaño: editá <span class="text-mono">--fs-base</span> y <span class="text-mono">--fs-table</span> en el CSS.
    </div>
  </div>
</div>

</div><!-- /conta-wrap -->

<?php
$content = ob_get_clean();
require __DIR__ . '/_layout.php';

/* ==========================================================
   =============== EXPORT ARCA (ZIP) COMPRAS =================
   ========================================================== */

function export_arca_zip_compras(PDO $pdo, string $desde, string $hasta, string $tipo): void
{
  if (!class_exists('ZipArchive')) {
    throw new RuntimeException("ZipArchive no está disponible. Instalá/activá php-zip.");
  }
  if (headers_sent($file, $line)) {
    throw new RuntimeException("Headers ya enviados en $file:$line. No se puede descargar ZIP.");
  }

  // Cabeceras
  $wh = ["f.fecha_emision BETWEEN :d AND :h"];
  $pa = [':d' => $desde, ':h' => $hasta];

  if ($tipo !== '') {
    $wh[] = "f.tipo_doc = :tipo";
    $pa[':tipo'] = $tipo;
  } else {
    $wh[] = "f.tipo_doc <> 'z'";
  }

  $where = "WHERE " . implode(" AND ", $wh);

  $sqlCbte = "
    SELECT
      f.id,
      f.fecha_emision AS fecha,
      f.tipo_doc,
      f.tipo_cbte,
      f.numero_factura,
      s.sup_cuit AS cuit,

      fp.total_ars         AS imp_total,
      fp.no_gravado_ars    AS imp_tot_conc,
      fp.exento_ars        AS imp_op_ex,
      (fp.perc_iva_ars + fp.perc_iibb_ars + fp.otros_imp_ars) AS imp_trib,

      COALESCE(SUM(CASE WHEN fid.alicuota > 0 THEN fid.neto_ars ELSE 0 END),0) AS imp_neto,
      COALESCE(SUM(CASE WHEN fid.alicuota > 0 THEN fid.iva_ars  ELSE 0 END),0) AS imp_iva

    FROM facturas f
    LEFT JOIN suppliers s ON s.sup_id = f.proveedor_id
    LEFT JOIN factura_price fp ON fp.factura_id = f.id
    LEFT JOIN factura_iva_detalle fid ON fid.factura_id = f.id
    $where
    GROUP BY f.id
    ORDER BY f.fecha_emision, f.id
  ";

  $st = $pdo->prepare($sqlCbte);
  $st->execute($pa);
  $cab = $st->fetchAll(PDO::FETCH_ASSOC);

  // Alícuotas agrupadas
  $sqlAli = "
    SELECT
      f.id AS factura_id,
      f.tipo_doc,
      f.tipo_cbte,
      f.numero_factura,
      fid.alicuota,
      SUM(fid.neto_ars) AS base_imp,
      SUM(fid.iva_ars)  AS imp_iva
    FROM facturas f
    JOIN factura_iva_detalle fid ON fid.factura_id = f.id
    $where
    GROUP BY f.id, f.tipo_doc, f.tipo_cbte, f.numero_factura, fid.alicuota
    ORDER BY f.id, fid.alicuota
  ";

  $st2 = $pdo->prepare($sqlAli);
  $st2->execute($pa);

  $alics = [];
  while ($r = $st2->fetch(PDO::FETCH_ASSOC)) {
    $alics[(int)$r['factura_id']][] = $r;
  }

  // Signo por factura (NC => -1)
  $signById = [];
  foreach ($cab as $r) {
    $signById[(int)$r['id']] = is_nc_compra([
      'tipo_doc' => $r['tipo_doc'] ?? '',
      'tipo_cbte'=> $r['tipo_cbte'] ?? 0
    ]) ? -1 : 1;
  }

  $cbteLines = [];
  foreach ($cab as $r) {
    $id = (int)$r['id'];
    $sign = $signById[$id] ?? 1;

    [$ptoVta, $nro] = parse_numero_factura($r['numero_factura']);

    $cantAlic = 0;
    if (!empty($alics[$id])) {
      foreach ($alics[$id] as $a) {
        $code = iva_code_from_percent_compras((float)$a['alicuota']);
        if ($code !== null) $cantAlic++;
      }
    }

    $cbteLines[] = build_cbte_line_compras([
      'fecha'        => $r['fecha'],
      'tipo_cbte'    => $r['tipo_cbte'],
      'pto_vta'      => $ptoVta,
      'cbte_nro'     => $nro,
      'doc_tipo'     => doc_tipo_from_cuit($r['cuit']),
      'doc_nro'      => $r['cuit'],

      // ✅ importes con signo (NC negativo)
      'imp_total'    => $sign * (float)$r['imp_total'],
      'imp_tot_conc' => $sign * (float)$r['imp_tot_conc'],
      'imp_neto'     => $sign * (float)$r['imp_neto'],
      'imp_op_ex'    => $sign * (float)$r['imp_op_ex'],
      'imp_iva'      => $sign * (float)$r['imp_iva'],
      'imp_trib'     => $sign * (float)$r['imp_trib'],

      'cant_alic'    => $cantAlic,
    ]);
  }

  $aliLines = [];
  foreach ($alics as $factId => $arr) {
    $sign = $signById[(int)$factId] ?? 1;

    foreach ($arr as $a) {
      $code = iva_code_from_percent_compras((float)$a['alicuota']);
      if ($code === null) continue;

      [$ptoVta, $nro] = parse_numero_factura($a['numero_factura']);

      $aliLines[] = implode(';', [
        padl((string)$a['tipo_cbte'], 3, '0'),
        padl((string)$ptoVta, 5, '0'),
        padl((string)$nro, 20, '0'),
        amt15($sign * (float)$a['base_imp']),
        $code,
        amt15($sign * (float)$a['imp_iva']),
      ]);
    }
  }

  // ZIP
  $tmpDir = sys_get_temp_dir() . '/arca_compras_' . uniqid();
  @mkdir($tmpDir, 0777, true);

  $f1 = $tmpDir . '/LIBRO_IVA_DIGITAL_COMPRAS_CBTE.txt';
  $f2 = $tmpDir . '/LIBRO_IVA_DIGITAL_COMPRAS_ALICUOTAS.txt';

  file_put_contents($f1, implode("\r\n", $cbteLines) . "\r\n");
  file_put_contents($f2, implode("\r\n", $aliLines) . "\r\n");

  $zipPath = $tmpDir . '/LIBRO_IVA_DIGITAL_COMPRAS_' . date('Ymd_His') . '.zip';
  $zip = new ZipArchive();
  if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
    throw new RuntimeException("No se pudo crear el ZIP.");
  }

  $zip->addFile($f1, basename($f1));
  $zip->addFile($f2, basename($f2));
  $zip->close();

  header('Content-Type: application/zip');
  header('Content-Disposition: attachment; filename="' . basename($zipPath) . '"');
  header('Content-Length: ' . filesize($zipPath));
  readfile($zipPath);
  exit;
}

/**
 * Layout “intercambio” separado por ;
 */
function build_cbte_line_compras(array $d): string
{
  return implode(';', [
    ymd($d['fecha']),
    padl((string)$d['tipo_cbte'], 3, '0'),
    padl((string)$d['pto_vta'], 5, '0'),
    padl((string)$d['cbte_nro'], 20, '0'),
    padl((string)$d['doc_tipo'], 2, '0'),
    padl(preg_replace('/\D+/', '', (string)$d['doc_nro']), 20, '0'),
    amt15($d['imp_total']),
    amt15($d['imp_tot_conc']),
    amt15($d['imp_neto']),
    amt15($d['imp_op_ex']),
    amt15($d['imp_iva']),
    amt15($d['imp_trib']),
    (string)(int)$d['cant_alic'],
  ]);
}

function parse_numero_factura(?string $nro): array
{
  $nro = trim((string)$nro);
  if ($nro === '') return [0, 0];

  if (preg_match('/^\s*(\d{1,5})\s*-\s*(\d{1,20})\s*$/', $nro, $m)) {
    return [(int)$m[1], (int)$m[2]];
  }
  if (preg_match('/^\s*(\d+)\s*-\s*(\d+)\s*$/', $nro, $m)) {
    return [(int)$m[1], (int)$m[2]];
  }

  $only = preg_replace('/\D+/', '', $nro);
  return [0, (int)($only !== '' ? $only : 0)];
}

function doc_tipo_from_cuit(?string $doc): int
{
  $doc = preg_replace('/\D+/', '', (string)$doc);
  if ($doc === '') return 99;
  if (strlen($doc) === 11) return 80; // CUIT
  if (strlen($doc) >= 7 && strlen($doc) <= 8) return 96; // DNI
  return 99;
}

function iva_code_from_percent_compras(float $p): ?string
{
  if (abs($p - 10.5) < 0.01) return '0004';
  if (abs($p - 21.0) < 0.01) return '0005';
  if (abs($p - 27.0) < 0.01) return '0006';
  return null; // 0% u otras: no van en alícuotas
}

function ymd($date): string
{
  if (!$date) return '00000000';
  $ts = strtotime((string)$date);
  return $ts ? date('Ymd', $ts) : '00000000';
}

function padl(string $s, int $len, string $ch = '0'): string
{
  $s = preg_replace('/\s+/', '', $s);
  if (strlen($s) > $len) $s = substr($s, -$len);
  return str_pad($s, $len, $ch, STR_PAD_LEFT);
}

/**
 * Monto con 2 decimales, sin separadores, ancho 15 (con signo)
 */
function amt15($n): string
{
  $v = (float)$n;
  $neg = $v < 0;
  $v = abs($v);
  $i = (int)round($v * 100);

  $s = padl((string)$i, 15, '0'); // 15 chars
  return $neg ? ('-'.substr($s, 1)) : $s; // mantiene longitud 15
}

function numcsv($n): string
{
  return number_format((float)$n, 2, '.', '');
}
