<?php
/* Conciliacion Yape para clientes2 (AGESCONT) - endpoint independiente.
   Usa los mismos JSON en /data. NO toca api.php.
   ?action=conciliar  (POST multipart, campo pdf)  -> analiza, NO escribe
   ?action=confirm    (POST json {items:[...]})     -> marca Pagado + aprende alias (con backup) */
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');

$dataDir  = __DIR__ . '/data';
$PAGOS    = $dataDir . '/pagos.json';
$CLIENTES = $dataDir . '/clientes.json';
$ALIASES  = $dataDir . '/yape_aliases.json';

function readJson($f, $assoc = true) { if (!file_exists($f)) return []; $d = json_decode(file_get_contents($f), $assoc); return $d === null ? [] : $d; }
function writeJson($f, $d) { return file_put_contents($f, json_encode($d, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)) !== false; }
function resp($ok, $data = null, $msg = '', $code = 200) { http_response_code($code); echo json_encode(['success' => $ok, 'data' => $data, 'message' => $msg], JSON_UNESCAPED_UNICODE); exit; }

$YAPE_STOP = ['SRL','SR','LTDA','CIA','COMPANY','COMPANIA','EMPRESARIALES','SERVICE','LOGISTIC','AND','DEL','LOS','LAS'];
function ynorm($s) { $s = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $s); $s = preg_replace('/[^A-Za-z0-9 ]/', ' ', $s); return strtoupper(trim(preg_replace('/\s+/', ' ', $s))); }
function ytokens($s) { global $YAPE_STOP; $o = []; foreach (explode(' ', ynorm($s)) as $t) { if (strlen($t) >= 3 && !in_array($t, $YAPE_STOP)) $o[$t] = 1; } return array_keys($o); }
function yamount($s) { return floatval(str_replace(',', '.', str_replace('.', '', $s))); }
function ypayer($d) { return trim(preg_replace('/^[A-Z]{2,5}\s*-\s*/', '', trim($d))); }
function yfiso($f) { $x = explode('/', $f); return count($x) == 3 ? sprintf('%s-%s-%s', $x[2], $x[1], $x[0]) : $f; }

function yparse($text) {
    $rows = []; $idx = -1;
    foreach (explode("\n", $text) as $line) {
        $t = trim($line);
        if ($t === '') continue;
        if (preg_match('#^(\d{2}/\d{2}/\d{4})\s+(\d{2}:\d{2}:\d{2})\s+(\d+)\s+(.*?)\s+([+\-])\s*Bs\s*([\d.,]+)\s+Bs\s*([\d.,]+)$#u', $t, $m)) {
            $mid = trim($m[4]); $parts = preg_split('/\s{2,}/', $mid);
            $desc = $parts[0] ?? ''; $detalle = count($parts) > 1 ? implode(' ', array_slice($parts, 1)) : '';
            $rows[] = ['fecha' => $m[1], 'hora' => $m[2], 'yapeId' => $m[3], 'desc' => $desc, 'detalle' => $detalle, 'sign' => $m[5], 'monto' => yamount($m[6])];
            $idx = count($rows) - 1;
        } elseif ($idx >= 0 && strpos($t, 'Bs') === false && stripos($t, 'verific') === false && stripos($t, 'Direcc') === false && stripos($t, 'supervis') === false && stripos($t, 'ayuda') === false) {
            $cont = preg_split('/\s{2,}/', $t);
            $rows[$idx]['desc'] = trim($rows[$idx]['desc'] . ' ' . ($cont[0] ?? ''));
            if (count($cont) > 1) $rows[$idx]['detalle'] = trim($rows[$idx]['detalle'] . ' ' . implode(' ', array_slice($cont, 1)));
        }
    }
    return $rows;
}

$action = $_GET['action'] ?? '';

if ($action === 'conciliar') {
    if (empty($_FILES['pdf']['tmp_name']) || !is_uploaded_file($_FILES['pdf']['tmp_name'])) resp(false, null, 'No se recibio el PDF (campo pdf)', 400);
    $text = shell_exec('pdftotext -layout ' . escapeshellarg($_FILES['pdf']['tmp_name']) . ' - 2>/dev/null');
    if (!$text) resp(false, null, 'No se pudo leer el PDF (pdftotext)', 500);

    $rows = yparse($text);
    $ingresos = array_values(array_filter($rows, fn($r) => $r['sign'] === '+'));

    $clientes = readJson($CLIENTES);
    $pagos    = readJson($PAGOS);
    $aliases  = readJson($ALIASES);
    if (!is_array($aliases)) $aliases = [];

    $cliTokens = []; $df = []; $cliName = [];
    foreach ($clientes as $c) {
        $tk = ytokens($c['razonSocial'] ?? '');
        $cliTokens[$c['id']] = $tk; $cliName[$c['id']] = $c['razonSocial'] ?? '';
        foreach ($tk as $t) $df[$t] = ($df[$t] ?? 0) + 1;
    }
    $refset = []; foreach ($pagos as $p) { if (!empty($p['refYape'])) $refset[$p['refYape']] = true; }
    $pend = array_values(array_filter($pagos, fn($p) => ($p['estado'] ?? '') === 'Pendiente'));

    $props = [];
    foreach ($ingresos as $r) {
        $pn = ypayer($r['desc']); $pnNorm = ynorm($pn); $amt = $r['monto']; $ptoks = ytokens($pn);
        $prop = ['yapeId' => $r['yapeId'], 'fecha' => $r['fecha'], 'fechaIso' => yfiso($r['fecha']), 'pagador' => $pn, 'pagadorNorm' => $pnNorm, 'monto' => $amt, 'detalle' => $r['detalle'], 'estado' => 'sin', 'clienteId' => null, 'clienteNombre' => '', 'pagoId' => null, 'concepto' => '', 'nCandMonto' => 0, 'incluir' => false];
        if (isset($refset[$r['yapeId']])) { $prop['estado'] = 'ya'; $props[] = $prop; continue; }

        $cid = $aliases[$pnNorm] ?? null; $viaAlias = $cid !== null;
        if ($cid === null) {
            $best = null;
            foreach ($cliTokens as $kcid => $tk) {
                if (!$tk) continue;
                $shared = array_values(array_intersect($ptoks, $tk));
                if (!$shared) continue;
                $strong = array_filter($shared, fn($t) => ($df[$t] ?? 99) <= 3);
                if (count($strong) >= 1 || count($shared) >= 3) {
                    $score = 0; foreach ($shared as $t) $score += 1.0 / max(1, ($df[$t] ?? 1));
                    if ($best === null || $score > $best['score']) $best = ['cid' => $kcid, 'score' => $score, 'shared' => count($shared)];
                }
            }
            if ($best) $cid = $best['cid'];
        }
        $sharedBest = $viaAlias ? 99 : ($best['shared'] ?? 0);
        $pendAmt = array_values(array_filter($pend, fn($p) => abs(floatval($p['monto'] ?? 0) - $amt) < 0.01));
        $prop['nCandMonto'] = count($pendAmt);

        if ($cid !== null) {
            $prop['clienteId'] = $cid; $prop['clienteNombre'] = $cliName[$cid] ?? '';
            $cpend = array_values(array_filter($pend, fn($p) => ($p['clienteId'] ?? null) == $cid));
            $exact = array_values(array_filter($cpend, fn($p) => abs(floatval($p['monto'] ?? 0) - $amt) < 0.01));
            $pick = $exact ? $exact[0] : ($cpend ? $cpend[0] : null);
            if ($pick) { $prop['pagoId'] = $pick['id']; $prop['concepto'] = $pick['concepto'] ?? ''; }
            if ($exact && $viaAlias) { $prop['estado'] = 'auto'; $prop['incluir'] = true; }
            elseif ($exact && $sharedBest >= 2) { $prop['estado'] = 'alta'; $prop['incluir'] = true; }
            else { $prop['estado'] = 'media'; }   // 1 sola palabra en comun o sin monto exacto -> revisar (no auto)
        } else {
            if (count($pendAmt) === 1) { $prop['estado'] = 'media_monto'; $prop['pagoId'] = $pendAmt[0]['id']; $prop['clienteId'] = $pendAmt[0]['clienteId'] ?? null; $prop['clienteNombre'] = $cliName[$prop['clienteId']] ?? ''; $prop['concepto'] = $pendAmt[0]['concepto'] ?? ''; }
            elseif (count($pendAmt) > 1) { $prop['estado'] = 'ambiguo'; }
        }
        $props[] = $prop;
    }

    // datos compactos para los desplegables del front
    $cliOut = []; foreach ($clientes as $c) { $cliOut[] = ['id' => $c['id'], 'nombre' => $c['razonSocial'] ?? '']; }
    usort($cliOut, fn($a, $b) => strcmp($a['nombre'], $b['nombre']));
    $pendOut = []; foreach ($pend as $p) { $pendOut[] = ['id' => $p['id'], 'clienteId' => $p['clienteId'] ?? null, 'monto' => $p['monto'] ?? 0, 'concepto' => $p['concepto'] ?? '', 'fechaVencimiento' => $p['fechaVencimiento'] ?? '']; }

    resp(true, ['ingresos' => count($ingresos), 'propuestas' => $props, 'clientes' => $cliOut, 'pendientes' => $pendOut], 'Extracto analizado');
}

elseif ($action === 'confirm') {
    $in = json_decode(file_get_contents('php://input'), true);
    if (!$in || empty($in['items']) || !is_array($in['items'])) resp(false, null, 'No se recibieron items', 400);

    $pagos = readJson($PAGOS);
    $aliases = readJson($ALIASES); if (!is_array($aliases)) $aliases = [];

    $bak = $GLOBALS['dataDir'] . '/pagos_backup_yape_' . date('Ymd_His') . '.json';
    @copy($GLOBALS['PAGOS'], $bak);

    $usedRef = []; foreach ($pagos as $p) { if (!empty($p['refYape'])) $usedRef[$p['refYape']] = true; }
    $byId = []; foreach ($pagos as $i => $p) { $byId[$p['id']] = $i; }

    $aplicados = 0; $aprendidos = 0; $omitidos = 0;
    foreach ($in['items'] as $it) {
        $pagoId = $it['pagoId'] ?? null; $yapeId = $it['yapeId'] ?? null; $clienteId = $it['clienteId'] ?? null;
        if ($pagoId === null || !isset($byId[$pagoId])) { $omitidos++; continue; }
        if ($yapeId && isset($usedRef[$yapeId])) { $omitidos++; continue; }
        $i = $byId[$pagoId];
        $pagos[$i]['estado'] = 'Pagado';
        $pagos[$i]['metodoPago'] = 'Yape';
        if (!empty($it['fechaIso'])) $pagos[$i]['fecha'] = $it['fechaIso'];
        $pagos[$i]['refYape'] = $yapeId;
        $nota = 'Conciliado Yape ' . $yapeId . (isset($it['pagador']) ? ' (' . $it['pagador'] . ')' : '');
        $pagos[$i]['notas'] = trim(($pagos[$i]['notas'] ?? '') . ' ' . $nota);
        if ($yapeId) $usedRef[$yapeId] = true;
        $aplicados++;
        if ($clienteId !== null && !empty($it['pagadorNorm'])) {
            if (($aliases[$it['pagadorNorm']] ?? null) != $clienteId) { $aliases[$it['pagadorNorm']] = $clienteId; $aprendidos++; }
        }
    }
    writeJson($GLOBALS['PAGOS'], $pagos);
    writeJson($GLOBALS['ALIASES'], $aliases);
    resp(true, ['aplicados' => $aplicados, 'aprendidos' => $aprendidos, 'omitidos' => $omitidos, 'backup' => basename($bak)], "Conciliados: $aplicados");
}

else {
    resp(false, null, 'Accion invalida. Use ?action=conciliar (POST pdf) o ?action=confirm (POST json).', 400);
}
