<?php
/**
 * Fusion Wayne v3 - API Test Harness
 * Autor: ChatGPT
 * Uso: sube este archivo como "test_fusion_api.php" a un servidor con PHP 7.4+
 *      y ábrelo en el navegador.
 *
 * IMPORTANTE:
 * - Este archivo NO controla bombas por sí solo; es un cliente de prueba.
 * - Asegúrate de usarlo en una red segura. Si tu API requiere autenticación,
 *   completa los campos de "Auth/Headers" en la UI.
 */

declare(strict_types=1);
ini_set('display_errors', '1');
error_reporting(E_ALL);
session_start();

// ===================== CONFIG =====================
$DEFAULT_BASE = 'http://172.17.125.102'; // Cambia si es necesario
$DEFAULT_TIMEOUT = 8; // segundos
$LOG_FILE = __DIR__ . '/fusion_api_test.log';

// =================== STATE / SESSION ==============
if (!isset($_SESSION['cfg'])) {
    $_SESSION['cfg'] = [
        'base' => $DEFAULT_BASE,
        'timeout' => $DEFAULT_TIMEOUT,
        'token' => '',
        'basic_user' => '',
        'basic_pass' => '',
        'cookies' => '',
        'verify_ssl' => '0', // "0" deshabilita verificación (HTTP local)
    ];
}
$cfg = &$_SESSION['cfg'];

// Update desde POST de configuración
if (($_POST['action'] ?? '') === 'save_cfg') {
    $cfg['base'] = trim((string)($_POST['base'] ?? $cfg['base']));
    $cfg['timeout'] = (int)($_POST['timeout'] ?? $cfg['timeout']);
    $cfg['token'] = trim((string)($_POST['token'] ?? $cfg['token']));
    $cfg['basic_user'] = trim((string)($_POST['basic_user'] ?? $cfg['basic_user']));
    $cfg['basic_pass'] = trim((string)($_POST['basic_pass'] ?? $cfg['basic_pass']));
    $cfg['cookies'] = trim((string)($_POST['cookies'] ?? $cfg['cookies']));
    $cfg['verify_ssl'] = (string)($_POST['verify_ssl'] ?? $cfg['verify_ssl']);
}

// ===================== HELPERS ====================
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }

function log_line(string $msg) : void {
    global $LOG_FILE;
    @file_put_contents($LOG_FILE, '['.date('Y-m-d H:i:s')."] ".$msg.PHP_EOL, FILE_APPEND);
}

function http_request(string $method, string $url, array $opts = []) : array {
    $ch = curl_init();
    $headers = [];
    $payload = $opts['payload'] ?? null;
    $timeout = (int)($opts['timeout'] ?? 8);
    $token   = (string)($opts['token'] ?? '');
    $basic   = $opts['basic'] ?? null; // ['user'=>'','pass'=>'']
    $cookies = (string)($opts['cookies'] ?? '');
    $verify  = (string)($opts['verify_ssl'] ?? '0');

    if (!empty($opts['headers']) && is_array($opts['headers'])) {
        foreach ($opts['headers'] as $k=>$v) {
            $headers[] = $k.': '.$v;
        }
    }
    if ($token !== '') {
        $headers[] = 'Authorization: Bearer ' . $token;
    }
    if ($cookies !== '') {
        curl_setopt($ch, CURLOPT_COOKIE, $cookies);
    }
    if (is_array($basic) && ($basic['user'] ?? '') !== '') {
        curl_setopt($ch, CURLOPT_USERPWD, $basic['user'].':'.($basic['pass'] ?? ''));
    }

    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_CUSTOMREQUEST => strtoupper($method),
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_SSL_VERIFYPEER => $verify === '1',
        CURLOPT_SSL_VERIFYHOST => $verify === '1' ? 2 : 0,
        CURLOPT_HEADER => true, // include headers in output
    ]);

    if ($payload !== null) {
        if (is_array($payload)) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
            if (!array_filter($headers, fn($h) => stripos($h, 'Content-Type:') === 0)) {
                $headers[] = 'Content-Type: application/x-www-form-urlencoded';
                curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            }
        } else {
            curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$payload);
        }
    }

    $raw = curl_exec($ch);
    $err = curl_error($ch);
    $info = curl_getinfo($ch);
    curl_close($ch);

    $status = $info['http_code'] ?? 0;
    $resp_headers = '';
    $resp_body = '';
    if ($raw !== false) {
        $header_size = $info['header_size'] ?? 0;
        $resp_headers = substr($raw, 0, $header_size);
        $resp_body = substr($raw, $header_size);
    }

    return [
        'ok' => ($err === ''),
        'error' => $err,
        'status' => $status,
        'info' => $info,
        'headers' => $resp_headers,
        'body' => $resp_body,
    ];
}

function pretty_json(string $s): string {
    $j = json_decode($s, true);
    if ($j === null) return $s;
    return json_encode($j, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

function join_url(string $base, string $path): string {
    $base = rtrim($base, '/');
    $path = ltrim($path, '/');
    return $base . '/' . $path;
}

// ================== ENDPOINT CATALOG ==================
// Descubiertos en tu carpeta /api/
$discovered = [
    ['GET',  '/api/prices.php',        'Listado de precios por manguera/producto'],
    ['GET',  '/api/sales.php',         'Ventas (histórico o rango por defecto)'],
    ['GET',  '/api/volumeByHose.php',  'Volumen del día por manguera'],
    ['GET',  '/api/attendant.php',     'Listado de operadores/atendentes'],
];

// Comunes en integraciones de dispenser (a probar/probing)
$probes = [
    ['GET',  '/api/transaction/last.php',      'Última transacción por bomba (?pump=ID)'],
    ['GET',  '/api/transaction/list.php',      'Transacciones por rango (?from=YYYY-MM-DD&to=YYYY-MM-DD)'],
    ['GET',  '/api/nozzle/status.php',         'Estado de boquillas'],
    ['GET',  '/api/pump/status.php',           'Estado de bombas'],
    ['POST', '/api/pump/authorize.php',        'Autorizar bomba (pump, amount, grade)'],
    ['POST', '/api/pump/release.php',          'Liberar/Finalizar bomba (pump)'],
    ['POST', '/api/fuel/setPrice.php',         'Cambiar precio (grade/hose, price)'],
];

// ================== ROUTER (Simple) ===================
$action = $_POST['action'] ?? $_GET['action'] ?? '';

// Ejecutar prueba única
if ($action === 'call_one') {
    $m = $_POST['method'] ?? 'GET';
    $p = $_POST['path'] ?? '/';
    $payload = $_POST['payload'] ?? '';
    $headers_json = $_POST['headers'] ?? '';

    $headers = [];
    if ($headers_json !== '') {
        // Soporta "Header-Name: value" por línea
        foreach (explode("\n", $headers_json) as $line) {
            $line = trim($line);
            if ($line === '') continue;
            if (strpos($line, ':') !== false) {
                [$k,$v] = array_map('trim', explode(':', $line, 2));
                $headers[$k] = $v;
            }
        }
    }

    $url = join_url($cfg['base'], $p);
    $res = http_request($m, $url, [
        'payload' => $payload === '' ? null : $payload,
        'timeout' => $cfg['timeout'],
        'token'   => $cfg['token'],
        'basic'   => ['user'=>$cfg['basic_user'], 'pass'=>$cfg['basic_pass']],
        'cookies' => $cfg['cookies'],
        'verify_ssl' => $cfg['verify_ssl'],
        'headers' => $headers,
    ]);

    log_line("{$m} {$url} => {$res['status']}  bytes=".strlen($res['body']));
    header('Content-Type: text/html; charset=utf-8');
    echo render_page($cfg, $discovered, $probes, $res, [
        'method'=>$m, 'path'=>$p, 'payload'=>$payload, 'headers'=>$headers_json
    ]);
    exit;
}

// Ejecutar suite rápida (discovered + probes)
if ($action === 'run_suite') {
    $results = [];
    foreach (array_merge($discovered, $probes) as $e) {
        [$m,$p,$desc] = $e;
        $url = join_url($cfg['base'], $p);
        $res = http_request($m, $url, [
            'timeout' => $cfg['timeout'],
            'token'   => $cfg['token'],
            'basic'   => ['user'=>$cfg['basic_user'], 'pass'=>$cfg['basic_pass']],
            'cookies' => $cfg['cookies'],
            'verify_ssl' => $cfg['verify_ssl'],
        ]);
        $results[] = ['method'=>$m,'path'=>$p,'desc'=>$desc,'response'=>$res];
        log_line("SUITE {$m} {$url} => {$res['status']}");
    }
    header('Content-Type: text/html; charset=utf-8');
    echo render_suite($cfg, $discovered, $probes, $results);
    exit;
}

// Render normal
header('Content-Type: text/html; charset=utf-8');
echo render_page($cfg, $discovered, $probes, null, null);

// ================== RENDER FUNCTIONS ==================
function render_page(array $cfg, array $discovered, array $probes, ?array $last=null, ?array $req=null): string {
    ob_start(); ?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fusion Wayne v3 - API Test</title>
<style>
:root{
    --bg:#0f172a; --card:#111827; --text:#e5e7eb; --muted:#94a3b8; --border:#1f2937; --good:#22c55e; --bad:#ef4444; --warn:#f59e0b;
}
*{box-sizing:border-box} body{margin:0;background:#0b1022;color:var(--text);font-family:system-ui,Segoe UI,Roboto}
.container{max-width:1200px;margin:0 auto;padding:16px}
.card{background:var(--card);border:1px solid var(--border);border-radius:12px;padding:14px;margin-bottom:16px}
h1{font-size:20px;margin:0 0 8px} h2{font-size:16px;margin:0 0 10px}
label{font-size:12px;color:var(--muted)} input,select,textarea{width:100%;padding:8px;border-radius:10px;border:1px solid var(--border);background:#0b1022;color:var(--text)}
.row{display:flex;gap:10px;flex-wrap:wrap} .col{flex:1;min-width:220px}
.btn{padding:10px 14px;border-radius:10px;border:1px solid var(--border);background:#0b1022;color:var(--text);cursor:pointer}
.btn:hover{opacity:.9} .btn-primary{background:linear-gradient(180deg,#16a34a,#15803d)} .btn-warn{background:linear-gradient(180deg,#f59e0b,#b45309)}
.kv{display:grid;grid-template-columns:180px 1fr;gap:6px;font-size:13px}
.pre{white-space:pre-wrap;background:#0b1022;border:1px solid var(--border);padding:8px;border-radius:8px;max-height:420px;overflow:auto}
.tag{display:inline-block;border:1px solid var(--border);padding:2px 8px;border-radius:999px;font-size:12px;color:var(--muted);margin-right:6px}
.status{font-weight:bold} .ok{color:var(--good)} .err{color:var(--bad)} .warn{color:var(--warn)}
.small{font-size:12px;color:var(--muted)}
</style>
</head>
<body>
<div class="container">
    <div class="card">
        <h1>Fusion Wayne v3 - API Test</h1>
        <form method="post" class="row" style="align-items:flex-end">
            <input type="hidden" name="action" value="save_cfg">
            <div class="col">
                <label>Base URL</label>
                <input type="text" name="base" value="<?=h($cfg['base'])?>" placeholder="http://172.17.125.102">
            </div>
            <div class="col">
                <label>Timeout (s)</label>
                <input type="number" name="timeout" value="<?=h((string)$cfg['timeout'])?>">
            </div>
            <div class="col">
                <label>Token (Bearer) (opcional)</label>
                <input type="text" name="token" value="<?=h($cfg['token'])?>" placeholder="ej: eyJ...">
            </div>
            <div class="col">
                <label>Basic Auth usuario</label>
                <input type="text" name="basic_user" value="<?=h($cfg['basic_user'])?>">
            </div>
            <div class="col">
                <label>Basic Auth password</label>
                <input type="password" name="basic_pass" value="<?=h($cfg['basic_pass'])?>">
            </div>
            <div class="col">
                <label>Cookies (opcional)</label>
                <input type="text" name="cookies" value="<?=h($cfg['cookies'])?>" placeholder="PHPSESSID=...; other=...">
            </div>
            <div class="col">
                <label>Verificar SSL</label>
                <select name="verify_ssl">
                    <option value="0" <?= $cfg['verify_ssl']==='0'?'selected':'' ?>>No (HTTP local)</option>
                    <option value="1" <?= $cfg['verify_ssl']==='1'?'selected':'' ?>>Sí</option>
                </select>
            </div>
            <div class="col" style="flex:0 0 auto">
                <button class="btn btn-primary">Guardar</button>
            </div>
        </form>
        <div class="small">Tip: Si el panel usa sesión/cookie, pega aquí las cookies que veas en el navegador (F12 → Application → Cookies).</div>
    </div>

    <div class="card">
        <h2>Suite rápida (descubiertos + a probar)</h2>
        <form method="post">
            <input type="hidden" name="action" value="run_suite">
            <div class="small" style="margin-bottom:8px;">
                Descubiertos: 
                <?php foreach($discovered as $d){ echo '<span class="tag">'.h($d[0].' '.$d[1]).'</span>'; } ?>
                <br>A probar: 
                <?php foreach($probes as $p){ echo '<span class="tag">'.h($p[0].' '.$p[1]).'</span>'; } ?>
            </div>
            <button class="btn btn-warn">Ejecutar suite</button>
        </form>
    </div>

    <div class="card">
        <h2>Llamada individual</h2>
        <form method="post">
            <input type="hidden" name="action" value="call_one">
            <div class="row">
                <div class="col">
                    <label>Método</label>
                    <select name="method">
                        <option>GET</option>
                        <option>POST</option>
                        <option>PUT</option>
                        <option>DELETE</option>
                    </select>
                </div>
                <div class="col">
                    <label>Path</label>
                    <input type="text" name="path" placeholder="/api/prices.php" value="/api/prices.php">
                </div>
                <div class="col">
                    <label>Payload (POST/PUT)</label>
                    <textarea name="payload" rows="3" placeholder="pump=3&amount=200.00&grade=1"></textarea>
                </div>
                <div class="col">
                    <label>Headers extra (uno por línea)</label>
                    <textarea name="headers" rows="3" placeholder="X-Api-Key: 12345&#10;Accept: application/json"></textarea>
                </div>
            </div>
            <div class="row" style="justify-content:flex-end">
                <button class="btn btn-primary">Ejecutar</button>
            </div>
        </form>
        <div class="small">Ejemplos de paths: /api/sales.php, /api/volumeByHose.php, /api/attendant.php</div>
    </div>

    <?php if ($last !== null): ?>
    <div class="card">
        <h2>Resultado</h2>
        <div class="kv">
            <div>URL</div><div><?=h($last['info']['url'] ?? '')?></div>
            <div>Método</div><div><?=h($last['info']['request_header'] ?? ($_POST['method'] ?? ''))?></div>
            <div>HTTP Status</div><div class="status <?= $last['status']>=200 && $last['status']<300 ? 'ok':'err' ?>"><?=h((string)$last['status'])?></div>
            <div>Tiempo</div><div><?=h((string)($last['info']['total_time'] ?? ''))?> s</div>
            <div>Tamaño</div><div><?=h((string)strlen($last['body']))?> bytes</div>
            <div>Error cURL</div><div class="<?= $last['error']===''?'ok':'err' ?>"><?=h($last['error'] ?: '—')?></div>
        </div>
        <h3>Headers respuesta</h3>
        <div class="pre"><?=h($last['headers'])?></div>
        <h3>Body (JSON pretty si aplica)</h3>
        <div class="pre"><?php echo h(pretty_json($last['body'])); ?></div>
        <h3>Body (raw)</h3>
        <div class="pre"><?=h($last['body'])?></div>

        <?php if ($req !== null): ?>
        <h3>Petición enviada</h3>
        <div class="pre"><?php
            echo "Method: ".h($req['method'])."\n";
            echo "Path:   ".h($req['path'])."\n";
            echo "Payload:\n".h($req['payload'])."\n\n";
            echo "Headers:\n".h($req['headers'])."\n";
        ?></div>
        <?php endif; ?>
    </div>
    <?php endif; ?>

    <div class="card">
        <h2>Notas y sugerencias</h2>
        <ul class="small">
            <li>Si algún endpoint responde 401/403, agrega Token/Básico/Cookies arriba y vuelve a probar.</li>
            <li>Para <b>autorizar bomba</b> (si existe): prueba <code>POST /api/pump/authorize.php</code> con <code>pump</code>, <code>amount</code>, <code>grade</code>.</li>
            <li>Para <b>cambiar precio</b> (si existe): <code>POST /api/fuel/setPrice.php</code> con <code>hose</code>/<code>grade</code> y <code>price</code>.</li>
            <li>Para <b>última venta</b>: prueba <code>GET /api/transaction/last.php?pump=1</code> (ajusta parámetros según tus bombas).</li>
            <li>Revisa F12 → Network en el POS original para "clonar" exactamente las llamadas.</li>
        </ul>
    </div>
</div>
</body>
</html>
<?php
} // render_page

function render_suite(array $cfg, array $discovered, array $probes, array $results): string {
    ob_start(); ?>
<!DOCTYPE html>
<html lang="es">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fusion Wayne v3 - Suite</title>
<style>
body{margin:0;background:#0b1022;color:#e5e7eb;font-family:system-ui,Segoe UI,Roboto}
.container{max-width:1200px;margin:0 auto;padding:16px}
.card{background:#111827;border:1px solid #1f2937;border-radius:12px;padding:14px;margin-bottom:16px}
h1{font-size:20px;margin:0 0 8px} .small{font-size:12px;color:#94a3b8}
table{width:100%;border-collapse:collapse} th,td{padding:8px;border-bottom:1px solid #1f2937;text-align:left;font-size:13px}
.ok{color:#22c55e} .err{color:#ef4444}
.pre{white-space:pre-wrap;background:#0b1022;border:1px solid #1f2937;padding:8px;border-radius:8px;max-height:260px;overflow:auto}
</style></head>
<body>
<div class="container">
    <div class="card"><h1>Suite rápida</h1></div>
    <div class="card">
        <table>
            <thead><tr><th>Método</th><th>Path</th><th>Descripción</th><th>Status</th><th>Tiempo</th><th>Bytes</th></tr></thead>
            <tbody>
            <?php foreach($results as $r): $res=$r['response']; ?>
                <tr>
                    <td><?=h($r['method'])?></td>
                    <td><?=h($r['path'])?></td>
                    <td class="small"><?=h($r['desc'])?></td>
                    <td class="<?= ($res['status']>=200 && $res['status']<300) ? 'ok':'err' ?>"><?=h((string)$res['status'])?></td>
                    <td class="small"><?=h((string)($res['info']['total_time'] ?? ''))?> s</td>
                    <td class="small"><?=h((string)strlen($res['body']))?></td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <div class="card small">
        <p>Consejo: Haz clic atrás en el navegador para volver y ejecutar llamadas individuales con payloads específicos.</p>
    </div>
</div>
</body></html>
<?php
    return ob_get_clean();
}
