{% extends "base.html" %}
{% block title %}Reverse Shell — AUTARCH{% endblock %}

{% block content %}
<div class="page-header">
    <h1>Reverse Shell</h1>
    <p>Remote device shell via Archon Companion App</p>
</div>

<!-- Listener Control -->
<div class="card">
    <div class="card-header">
        <h3>Listener</h3>
        <span id="listenerStatus" class="status-badge {% if running %}status-good{% else %}status-bad{% endif %}">
            {{ 'Running' if running else 'Stopped' }}
        </span>
    </div>
    <div class="card-body">
        <div class="form-row">
            <div class="form-group">
                <label>Port</label>
                <input type="number" id="listenerPort" value="{{ port }}" class="form-input" style="width:100px">
            </div>
            <div class="form-group">
                <label>Token</label>
                <input type="text" id="listenerToken" value="{{ token }}" class="form-input" style="width:300px" readonly>
            </div>
            <div class="form-group" style="padding-top:24px">
                <button onclick="rsListenerStart()" class="btn btn-primary" id="btnStart">Start</button>
                <button onclick="rsListenerStop()" class="btn btn-danger" id="btnStop">Stop</button>
                <button onclick="rsRefreshSessions()" class="btn btn-secondary">Refresh</button>
            </div>
        </div>
        <p class="help-text">
            On the Archon app: Modules tab → Reverse Shell → CONNECT.<br>
            The device will connect back to this listener on port <strong id="portDisplay">{{ port }}</strong>.
        </p>
    </div>
</div>

<!-- Sessions -->
<div class="card">
    <div class="card-header">
        <h3>Sessions</h3>
        <span id="sessionCount" class="status-badge">{{ sessions|length }}</span>
    </div>
    <div class="card-body">
        <div id="sessionList">
            {% if sessions %}
                {% for s in sessions %}
                <div class="session-card" data-sid="{{ s.session_id }}">
                    <div class="session-info">
                        <strong>{{ s.device }}</strong>
                        <span class="dim">Android {{ s.android }} | UID {{ s.uid }}</span>
                        <span class="dim">Connected {{ s.connected_at }} | {{ s.commands_executed }} cmds</span>
                    </div>
                    <div class="session-actions">
                        <button onclick="rsSelectSession('{{ s.session_id }}')" class="btn btn-primary btn-sm">Select</button>
                        <button onclick="rsDisconnect('{{ s.session_id }}')" class="btn btn-danger btn-sm">Disconnect</button>
                    </div>
                </div>
                {% endfor %}
            {% else %}
                <p class="dim">No active sessions. Start the listener and connect from the Archon app.</p>
            {% endif %}
        </div>
    </div>
</div>

<!-- Terminal -->
<div class="card" id="terminalCard" style="display:none">
    <div class="card-header">
        <h3>Terminal — <span id="termDevice">?</span></h3>
        <div>
            <button onclick="rsSysinfo()" class="btn btn-secondary btn-sm">SysInfo</button>
            <button onclick="rsScreenshot()" class="btn btn-secondary btn-sm">Screenshot</button>
            <button onclick="rsPackages()" class="btn btn-secondary btn-sm">Packages</button>
            <button onclick="rsProcesses()" class="btn btn-secondary btn-sm">Processes</button>
            <button onclick="rsNetstat()" class="btn btn-secondary btn-sm">Netstat</button>
            <button onclick="rsLogcat()" class="btn btn-secondary btn-sm">Logcat</button>
        </div>
    </div>
    <div class="card-body">
        <div id="termOutput" class="terminal-output"></div>
        <div class="terminal-input-row">
            <span class="terminal-prompt">shell@device:/ $</span>
            <input type="text" id="termInput" class="terminal-input"
                   placeholder="Type command and press Enter"
                   onkeydown="if(event.key==='Enter')rsExecCmd()">
            <button onclick="rsExecCmd()" class="btn btn-primary btn-sm">Run</button>
        </div>
    </div>
</div>

<!-- File Transfer -->
<div class="card" id="fileCard" style="display:none">
    <div class="card-header">
        <h3>File Transfer</h3>
    </div>
    <div class="card-body">
        <div class="form-row">
            <div class="form-group">
                <label>Download from device</label>
                <input type="text" id="downloadPath" class="form-input" placeholder="/sdcard/file.txt">
                <button onclick="rsDownload()" class="btn btn-secondary btn-sm" style="margin-top:4px">Download</button>
            </div>
            <div class="form-group">
                <label>Upload to device</label>
                <input type="file" id="uploadFile" class="form-input">
                <input type="text" id="uploadPath" class="form-input" placeholder="/data/local/tmp/file" style="margin-top:4px">
                <button onclick="rsUpload()" class="btn btn-secondary btn-sm" style="margin-top:4px">Upload</button>
            </div>
        </div>
    </div>
</div>

<!-- Screenshot Preview -->
<div class="card" id="screenshotCard" style="display:none">
    <div class="card-header">
        <h3>Screenshot</h3>
    </div>
    <div class="card-body" style="text-align:center">
        <img id="screenshotImg" style="max-width:100%;max-height:600px;border:1px solid var(--border)">
    </div>
</div>

<style>
.session-card {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px;
    margin-bottom: 8px;
    background: var(--surface-dark);
    border: 1px solid var(--border);
    border-radius: 4px;
}
.session-card.selected {
    border-color: var(--primary);
}
.session-info { display: flex; flex-direction: column; gap: 2px; }
.session-actions { display: flex; gap: 6px; }
.terminal-output {
    background: #0a0a0a;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 12px;
    font-family: 'Courier New', monospace;
    font-size: 13px;
    color: #00ff41;
    min-height: 300px;
    max-height: 500px;
    overflow-y: auto;
    white-space: pre-wrap;
    word-break: break-all;
}
.terminal-input-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    background: #0a0a0a;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 8px 12px;
}
.terminal-prompt {
    color: #00ff41;
    font-family: 'Courier New', monospace;
    font-size: 13px;
    white-space: nowrap;
}
.terminal-input {
    flex: 1;
    background: transparent;
    border: none;
    color: #fff;
    font-family: 'Courier New', monospace;
    font-size: 13px;
    outline: none;
}
.dim { color: var(--text-secondary); font-size: 12px; }
.form-row { display: flex; gap: 16px; flex-wrap: wrap; }
.form-group { display: flex; flex-direction: column; }
.form-group label { font-size: 12px; color: var(--text-secondary); margin-bottom: 4px; }
.help-text { font-size: 12px; color: var(--text-secondary); margin-top: 8px; }
.status-badge {
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 12px;
    font-weight: bold;
}
.status-good { background: #1a3a1a; color: #00ff41; }
.status-bad { background: #3a1a1a; color: #ff4444; }
.term-error { color: #ff4444; }
.term-info { color: #4488ff; }
.term-cmd { color: #888; }
</style>

<script>
let currentSession = null;
const cmdHistory = [];
let historyIdx = -1;

// ── Listener ───────────────────────────────────────────

function rsListenerStart() {
    const port = document.getElementById('listenerPort').value;
    fetchJSON('/revshell/listener/start', {port: parseInt(port)}, r => {
        if (r.success) {
            document.getElementById('listenerToken').value = r.token;
            document.getElementById('portDisplay').textContent = port;
            showStatus('listenerStatus', true, 'Running');
            termLog('Listener started on port ' + port, 'info');
        } else {
            termLog('Failed: ' + r.message, 'error');
        }
    });
}

function rsListenerStop() {
    fetchJSON('/revshell/listener/stop', {}, r => {
        showStatus('listenerStatus', false, 'Stopped');
        termLog('Listener stopped', 'info');
        document.getElementById('sessionList').innerHTML = '<p class="dim">No active sessions.</p>';
    });
}

function rsRefreshSessions() {
    fetchJSON('/revshell/sessions', {}, r => {
        const list = document.getElementById('sessionList');
        const count = document.getElementById('sessionCount');
        if (!r.sessions || r.sessions.length === 0) {
            list.innerHTML = '<p class="dim">No active sessions.</p>';
            count.textContent = '0';
            return;
        }
        count.textContent = r.sessions.length;
        list.innerHTML = r.sessions.map(s => `
            <div class="session-card ${currentSession === s.session_id ? 'selected' : ''}" data-sid="${s.session_id}">
                <div class="session-info">
                    <strong>${esc(s.device)}</strong>
                    <span class="dim">Android ${esc(s.android)} | UID ${s.uid} | ${s.commands_executed} cmds | ${formatUptime(s.uptime)}</span>
                </div>
                <div class="session-actions">
                    <button onclick="rsSelectSession('${s.session_id}')" class="btn btn-primary btn-sm">Select</button>
                    <button onclick="rsDisconnect('${s.session_id}')" class="btn btn-danger btn-sm">Disconnect</button>
                </div>
            </div>
        `).join('');
    });
}

// ── Session ────────────────────────────────────────────

function rsSelectSession(sid) {
    currentSession = sid;
    document.getElementById('terminalCard').style.display = '';
    document.getElementById('fileCard').style.display = '';
    document.querySelectorAll('.session-card').forEach(el => {
        el.classList.toggle('selected', el.dataset.sid === sid);
    });

    fetchJSON(`/revshell/session/${sid}/info`, {}, r => {
        if (r.success) {
            document.getElementById('termDevice').textContent =
                r.session.device + ' (Android ' + r.session.android + ')';
        }
    });

    clearTerm();
    termLog('Session selected: ' + sid, 'info');
    document.getElementById('termInput').focus();
}

function rsDisconnect(sid) {
    if (!confirm('Disconnect this session?')) return;
    fetchJSON(`/revshell/session/${sid}/disconnect`, {}, r => {
        termLog(r.message, r.success ? 'info' : 'error');
        if (sid === currentSession) {
            currentSession = null;
            document.getElementById('terminalCard').style.display = 'none';
            document.getElementById('fileCard').style.display = 'none';
        }
        rsRefreshSessions();
    });
}

// ── Terminal ───────────────────────────────────────────

function rsExecCmd() {
    if (!currentSession) { termLog('No session selected', 'error'); return; }
    const input = document.getElementById('termInput');
    const cmd = input.value.trim();
    if (!cmd) return;

    cmdHistory.unshift(cmd);
    historyIdx = -1;
    input.value = '';

    termLog('$ ' + cmd, 'cmd');
    fetchJSON(`/revshell/session/${currentSession}/execute`, {cmd: cmd}, r => {
        if (r.stdout) termLog(r.stdout);
        if (r.stderr) termLog(r.stderr, 'error');
        if (r.exit_code !== 0) termLog('[exit: ' + r.exit_code + ']', 'error');
    });
}

document.addEventListener('keydown', e => {
    const input = document.getElementById('termInput');
    if (document.activeElement !== input) return;
    if (e.key === 'ArrowUp' && cmdHistory.length > 0) {
        historyIdx = Math.min(historyIdx + 1, cmdHistory.length - 1);
        input.value = cmdHistory[historyIdx];
        e.preventDefault();
    } else if (e.key === 'ArrowDown') {
        historyIdx = Math.max(historyIdx - 1, -1);
        input.value = historyIdx >= 0 ? cmdHistory[historyIdx] : '';
        e.preventDefault();
    }
});

// ── Quick Actions ──────────────────────────────────────

function rsSysinfo() {
    if (!currentSession) return;
    termLog('--- System Info ---', 'info');
    fetchJSON(`/revshell/session/${currentSession}/sysinfo`, {}, r => {
        termLog(r.stdout || r.stderr || r.message);
    });
}

function rsScreenshot() {
    if (!currentSession) return;
    termLog('Capturing screenshot...', 'info');
    const img = document.getElementById('screenshotImg');
    img.src = `/revshell/session/${currentSession}/screenshot/view?t=` + Date.now();
    document.getElementById('screenshotCard').style.display = '';
    img.onerror = () => termLog('Screenshot failed', 'error');
    img.onload = () => termLog('Screenshot captured', 'info');
}

function rsPackages() {
    if (!currentSession) return;
    termLog('--- Installed Packages ---', 'info');
    fetchJSON(`/revshell/session/${currentSession}/packages`, {}, r => {
        termLog(r.stdout || r.stderr || r.message);
    });
}

function rsProcesses() {
    if (!currentSession) return;
    termLog('--- Processes ---', 'info');
    fetchJSON(`/revshell/session/${currentSession}/processes`, {}, r => {
        termLog(r.stdout || r.stderr || r.message);
    });
}

function rsNetstat() {
    if (!currentSession) return;
    termLog('--- Network Connections ---', 'info');
    fetchJSON(`/revshell/session/${currentSession}/netstat`, {}, r => {
        termLog(r.stdout || r.stderr || r.message);
    });
}

function rsLogcat() {
    if (!currentSession) return;
    termLog('--- Logcat (last 50 lines) ---', 'info');
    fetchJSON(`/revshell/session/${currentSession}/logcat`, {lines: 50}, r => {
        termLog(r.stdout || r.stderr || r.message);
    });
}

// ── File Transfer ──────────────────────────────────────

function rsDownload() {
    if (!currentSession) return;
    const path = document.getElementById('downloadPath').value.trim();
    if (!path) { termLog('No path specified', 'error'); return; }
    termLog('Downloading: ' + path, 'info');
    fetchJSON(`/revshell/session/${currentSession}/download`, {path: path}, r => {
        termLog(r.success ? 'Saved to: ' + r.path : 'Failed: ' + r.message, r.success ? 'info' : 'error');
    });
}

function rsUpload() {
    if (!currentSession) return;
    const fileInput = document.getElementById('uploadFile');
    const remotePath = document.getElementById('uploadPath').value.trim();
    if (!fileInput.files[0] || !remotePath) {
        termLog('Select a file and specify remote path', 'error');
        return;
    }
    termLog('Uploading to: ' + remotePath, 'info');
    const fd = new FormData();
    fd.append('file', fileInput.files[0]);
    fd.append('path', remotePath);
    fetch(`/revshell/session/${currentSession}/upload`, {method:'POST', body:fd})
        .then(r => r.json())
        .then(r => termLog(r.success ? r.stdout : 'Failed: ' + r.stderr, r.success ? 'info' : 'error'));
}

// ── Helpers ────────────────────────────────────────────

function termLog(text, type) {
    const out = document.getElementById('termOutput');
    if (!out) return;
    const span = document.createElement('span');
    if (type === 'error') span.className = 'term-error';
    else if (type === 'info') span.className = 'term-info';
    else if (type === 'cmd') span.className = 'term-cmd';
    span.textContent = text + '\n';
    out.appendChild(span);
    out.scrollTop = out.scrollHeight;
}

function clearTerm() {
    const out = document.getElementById('termOutput');
    if (out) out.innerHTML = '';
}

function showStatus(id, good, text) {
    const el = document.getElementById(id);
    el.textContent = text;
    el.className = 'status-badge ' + (good ? 'status-good' : 'status-bad');
}

function formatUptime(sec) {
    if (sec < 60) return sec + 's';
    if (sec < 3600) return Math.floor(sec/60) + 'm';
    return Math.floor(sec/3600) + 'h ' + Math.floor((sec%3600)/60) + 'm';
}

function esc(s) { const d = document.createElement('div'); d.textContent = s; return d.innerHTML; }

function fetchJSON(url, data, cb) {
    fetch(url, {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(data)
    }).then(r => r.json()).then(cb).catch(e => {
        if (typeof termLog === 'function') termLog('Request failed: ' + e, 'error');
    });
}

// Auto-refresh sessions every 10s
setInterval(rsRefreshSessions, 10000);
</script>
{% endblock %}
