{% extends "base.html" %}
{% block title %}Offense - AUTARCH{% endblock %}

{% block content %}
<div class="page-header">
    <h1>Offense</h1>
</div>

<!-- MSF Status -->
<div class="section">
    <h2>Metasploit Status</h2>
    <div class="status-indicator" id="msf-status">
        <span class="status-dot inactive"></span>Checking...
    </div>
    <div id="msf-info" style="font-size:0.85rem;color:var(--text-secondary);margin-top:4px"></div>
    <p style="font-size:0.8rem;color:var(--text-muted);margin-top:8px">Module execution is CLI-only for safety. The web UI provides search, browsing, and status.</p>
</div>

<!-- Module Search -->
<div class="section">
    <h2>Module Search</h2>
    <div class="input-row">
        <input type="text" id="msf-search" placeholder="Search modules (e.g., eternalblue, smb, ssh)" onkeypress="if(event.key==='Enter')searchMSFModules()">
        <button id="btn-msf-search" class="btn btn-primary" onclick="searchMSFModules()">Search</button>
    </div>
    <div id="msf-search-results" class="results-stream" style="max-height:400px;overflow-y:auto">
        <div class="empty-state">Search the offline module library or connected MSF instance.</div>
    </div>
</div>

<!-- Module Browser -->
<div class="section">
    <h2>Module Browser</h2>
    <div class="tab-bar">
        <button class="tab active" data-tab-group="msf-browse" data-tab="auxiliary" onclick="showTab('msf-browse','auxiliary');browseMSFModules('auxiliary')">Scanners</button>
        <button class="tab" data-tab-group="msf-browse" data-tab="exploit" onclick="showTab('msf-browse','exploit');browseMSFModules('exploit')">Exploits</button>
        <button class="tab" data-tab-group="msf-browse" data-tab="post" onclick="showTab('msf-browse','post');browseMSFModules('post')">Post</button>
        <button class="tab" data-tab-group="msf-browse" data-tab="payload" onclick="showTab('msf-browse','payload');browseMSFModules('payload')">Payloads</button>
    </div>
    <input type="hidden" id="msf-page-auxiliary" value="1">
    <input type="hidden" id="msf-page-exploit" value="1">
    <input type="hidden" id="msf-page-post" value="1">
    <input type="hidden" id="msf-page-payload" value="1">
    <div class="tab-content active" data-tab-group="msf-browse" data-tab="auxiliary" id="msf-modules-auxiliary">
        <div class="empty-state">Click a tab to browse modules.</div>
    </div>
    <div class="tab-content" data-tab-group="msf-browse" data-tab="exploit" id="msf-modules-exploit"></div>
    <div class="tab-content" data-tab-group="msf-browse" data-tab="post" id="msf-modules-post"></div>
    <div class="tab-content" data-tab-group="msf-browse" data-tab="payload" id="msf-modules-payload"></div>
</div>

<!-- Sessions -->
<div class="section">
    <h2>Active Sessions</h2>
    <div class="tool-actions">
        <button class="btn btn-small" onclick="loadMSFSessions()">Refresh</button>
    </div>
    <div id="msf-sessions">
        <div class="empty-state">Click "Refresh" to check for active sessions.</div>
    </div>
</div>

{% if modules %}
<div class="section">
    <h2>Offense Modules</h2>
    <ul class="module-list">
    {% for name, info in modules.items() %}
        <li class="module-item">
            <div>
                <div class="module-name">{{ name }}</div>
                <div class="module-desc">{{ info.description }}</div>
            </div>
            <div class="module-meta">v{{ info.version }}</div>
        </li>
    {% endfor %}
    </ul>
</div>
{% endif %}

<!-- Run Module -->
<div class="section">
    <h2>Run Module</h2>
    <div class="tab-bar">
        <button class="tab active" data-tab-group="run-tabs" data-tab="ssh"      onclick="showTab('run-tabs','ssh')">SSH</button>
        <button class="tab"        data-tab-group="run-tabs" data-tab="portscan"  onclick="showTab('run-tabs','portscan')">Port Scan</button>
        <button class="tab"        data-tab-group="run-tabs" data-tab="osdetect"  onclick="showTab('run-tabs','osdetect')">OS Detect</button>
        <button class="tab"        data-tab-group="run-tabs" data-tab="custom"    onclick="showTab('run-tabs','custom')">Custom</button>
    </div>

    <!-- SSH tab -->
    <div class="tab-content active" data-tab-group="run-tabs" data-tab="ssh">
        <div style="display:grid;grid-template-columns:1fr auto auto;gap:0.75rem;align-items:end;margin-top:0.75rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="ssh-rhosts">Target(s)</label>
                <input type="text" id="ssh-rhosts" placeholder="192.168.1.0/24 or 10.0.0.5">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="ssh-rport">Port</label>
                <input type="text" id="ssh-rport" value="22" style="width:70px">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="ssh-threads">Threads</label>
                <input type="text" id="ssh-threads" value="10" style="width:60px">
            </div>
        </div>
        <div class="tool-actions" style="margin-top:0.75rem">
            <button class="btn btn-primary" onclick="runFeaturedModule('ssh')">Run SSH Version Scan</button>
            <button class="btn btn-secondary" onclick="toggleBruteRow()">SSH Brute-Force &darr;</button>
        </div>
        <div id="ssh-brute-row" style="display:none;margin-top:0.5rem">
            <div style="display:grid;grid-template-columns:1fr 1fr auto;gap:0.75rem;align-items:end">
                <div class="form-group" style="margin-bottom:0">
                    <label for="ssh-username">Username</label>
                    <input type="text" id="ssh-username" placeholder="root">
                </div>
                <div class="form-group" style="margin-bottom:0">
                    <label for="ssh-password">Password</label>
                    <input type="text" id="ssh-password" placeholder="password">
                </div>
                <button class="btn btn-danger" onclick="runFeaturedModule('ssh-brute')">Run Brute-Force</button>
            </div>
        </div>
    </div>

    <!-- Port Scan tab -->
    <div class="tab-content" data-tab-group="run-tabs" data-tab="portscan">
        <div style="display:grid;grid-template-columns:1fr auto auto;gap:0.75rem;align-items:end;margin-top:0.75rem">
            <div class="form-group" style="margin-bottom:0">
                <label for="ps-rhosts">Target(s)</label>
                <input type="text" id="ps-rhosts" placeholder="192.168.1.0/24 or 10.0.0.5">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="ps-ports">Ports</label>
                <input type="text" id="ps-ports" value="1-1024" style="width:100px">
            </div>
            <div class="form-group" style="margin-bottom:0">
                <label for="ps-threads">Threads</label>
                <input type="text" id="ps-threads" value="10" style="width:60px">
            </div>
        </div>
        <div class="tool-actions" style="margin-top:0.75rem">
            <button class="btn btn-primary" onclick="runFeaturedModule('tcp-scan')">Run TCP Scan</button>
            <button class="btn btn-secondary" onclick="runFeaturedModule('syn-scan')">Run SYN Scan</button>
        </div>
    </div>

    <!-- OS Detect tab -->
    <div class="tab-content" data-tab-group="run-tabs" data-tab="osdetect">
        <div style="margin-top:0.75rem">
            <div class="form-group">
                <label for="os-rhosts">Target(s)</label>
                <input type="text" id="os-rhosts" placeholder="192.168.1.0/24 or 10.0.0.5">
            </div>
        </div>
        <div class="tool-actions">
            <button class="btn btn-primary" onclick="runFeaturedModule('smb-version')">Run SMB Version</button>
            <button class="btn btn-secondary" onclick="runFeaturedModule('http-header')">Run HTTP Header</button>
        </div>
    </div>

    <!-- Custom tab -->
    <div class="tab-content" data-tab-group="run-tabs" data-tab="custom">
        <div style="margin-top:0.75rem">
            <div class="form-group">
                <label for="custom-module">Module Path</label>
                <input type="text" id="custom-module" placeholder="auxiliary/scanner/ssh/ssh_version">
            </div>
            <div class="form-group">
                <label for="custom-options">Options (JSON)</label>
                <input type="text" id="custom-options" placeholder='{"RHOSTS":"10.0.0.1","RPORT":22}'>
            </div>
        </div>
        <div class="tool-actions">
            <button class="btn btn-primary" onclick="runFeaturedModule('custom')">Run Module</button>
        </div>
    </div>

    <!-- Shared output area -->
    <div style="margin-top:0.75rem;display:flex;align-items:center;gap:0.75rem;padding-top:0.5rem;border-top:1px solid var(--border)">
        <span id="run-status" style="font-size:0.85rem;color:var(--text-secondary);flex:1"></span>
        <button id="run-stop-btn" class="btn btn-sm btn-danger" style="display:none" onclick="stopCurrentModule()">Stop</button>
    </div>
    <div id="module-output" class="results-stream" style="min-height:140px;margin-top:0.5rem"></div>
</div>

<!-- Agent Hal -->
<div class="section">
    <h2>Agent Hal — Autonomous Mode</h2>
    <p style="font-size:0.85rem;color:var(--text-secondary);margin-bottom:0.75rem">Give Hal a security task and watch it execute step by step using MSF and other tools.</p>
    <div class="input-row">
        <input type="text" id="agent-task" placeholder="e.g. scan 10.0.0.5 for open SSH ports and identify the service version">
        <button class="btn btn-primary" onclick="runHalTask()">Run</button>
        <button id="agent-stop-btn" class="btn btn-danger" style="display:none" onclick="stopHalTask()">Stop</button>
    </div>
    <div id="agent-output" class="results-stream" style="min-height:120px"></div>
</div>

<script>
let _currentJobId = null;
let _currentRunId = null;

// Check MSF status on page load
document.addEventListener('DOMContentLoaded', function() { checkMSFStatus(); });

const _FEATURED = {
    'ssh':        {path: 'auxiliary/scanner/ssh/ssh_version',  opts: () => ({RHOSTS: v('ssh-rhosts'), RPORT: parseInt(v('ssh-rport')) || 22, THREADS: parseInt(v('ssh-threads')) || 10})},
    'ssh-brute':  {path: 'auxiliary/scanner/ssh/ssh_login',    opts: () => ({RHOSTS: v('ssh-rhosts'), RPORT: parseInt(v('ssh-rport')) || 22, USERNAME: v('ssh-username'), PASSWORD: v('ssh-password')})},
    'tcp-scan':   {path: 'auxiliary/scanner/portscan/tcp',     opts: () => ({RHOSTS: v('ps-rhosts'), PORTS: v('ps-ports') || '1-1024', THREADS: parseInt(v('ps-threads')) || 10})},
    'syn-scan':   {path: 'auxiliary/scanner/portscan/syn',     opts: () => ({RHOSTS: v('ps-rhosts'), PORTS: v('ps-ports') || '1-1024', THREADS: parseInt(v('ps-threads')) || 10})},
    'smb-version':{path: 'auxiliary/scanner/smb/smb_version',  opts: () => ({RHOSTS: v('os-rhosts')})},
    'http-header':{path: 'auxiliary/scanner/http/http_header', opts: () => ({RHOSTS: v('os-rhosts')})},
    'custom':     {path: null, opts: () => {try{return JSON.parse(v('custom-options') || '{}')}catch(e){return {}}}},
};

function v(id) { const el = document.getElementById(id); return el ? el.value.trim() : ''; }

function toggleBruteRow() {
    var row = document.getElementById('ssh-brute-row');
    row.style.display = row.style.display === 'none' ? '' : 'none';
}

function runFeaturedModule(key) {
    const cfg = _FEATURED[key];
    if (!cfg) return;
    const path = key === 'custom' ? v('custom-module') : cfg.path;
    if (!path) { alert('Enter a module path'); return; }
    const opts = cfg.opts();
    if (!opts.RHOSTS && key !== 'custom') { alert('Enter a target in RHOSTS'); return; }
    runModule(path, opts);
}

function runModule(module_path, options) {
    const out = document.getElementById('module-output');
    const status = document.getElementById('run-status');
    const stopBtn = document.getElementById('run-stop-btn');
    out.innerHTML = '';
    status.textContent = 'Starting...';
    stopBtn.style.display = '';
    _currentJobId = null;

    const es = new EventSource('/offense/module/run?' + new URLSearchParams({_body: JSON.stringify({module_path, options})}));

    // Use fetch + ReadableStream (EventSource doesn't support POST)
    es.close();
    fetch('/offense/module/run', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({module_path, options})
    }).then(res => {
        const reader = res.body.getReader();
        const dec = new TextDecoder();
        let buf = '';
        function pump() {
            reader.read().then(({done, value}) => {
                if (done) { status.textContent = 'Finished.'; stopBtn.style.display = 'none'; return; }
                buf += dec.decode(value, {stream: true});
                const parts = buf.split('\n\n');
                buf = parts.pop();
                parts.forEach(part => {
                    const line = part.replace(/^data:\s*/, '').trim();
                    if (!line) return;
                    try {
                        const d = JSON.parse(line);
                        if (d.job_id) { _currentJobId = d.job_id; status.textContent = 'Running…'; }
                        if (d.error) { out.innerHTML += '<div class="err">Error: ' + escapeHtml(d.error) + '</div>'; stopBtn.style.display = 'none'; }
                        if (d.line)  { out.innerHTML += '<div>' + escapeHtml(d.line) + '</div>'; out.scrollTop = out.scrollHeight; }
                        if (d.done)  {
                            status.textContent = 'Done.';
                            stopBtn.style.display = 'none';
                            if (d.open_ports && d.open_ports.length) out.innerHTML += '<div class="success">Open ports: ' + escapeHtml(d.open_ports.join(', ')) + '</div>';
                            if (d.findings && d.findings.length) out.innerHTML += '<div class="success">Findings: ' + escapeHtml(JSON.stringify(d.findings)) + '</div>';
                        }
                    } catch(e) {}
                });
                pump();
            }).catch(e => { status.textContent = 'Error.'; out.innerHTML += '<div class="err">' + escapeHtml(e.message) + '</div>'; stopBtn.style.display = 'none'; });
        }
        pump();
    }).catch(e => { status.textContent = 'Failed.'; out.innerHTML = '<div class="err">' + escapeHtml(e.message) + '</div>'; stopBtn.style.display = 'none'; });
}

function stopCurrentModule() {
    if (!_currentJobId) return;
    fetch('/offense/module/stop', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({job_id: _currentJobId})});
    document.getElementById('run-stop-btn').style.display = 'none';
    document.getElementById('run-status').textContent = 'Stopped.';
}

// Agent Hal
async function runHalTask() {
    const task = v('agent-task');
    if (!task) return;
    const out = document.getElementById('agent-output');
    out.innerHTML = '';
    document.getElementById('agent-stop-btn').style.display = '';
    const res = await fetch('/api/agent/run', {method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({task})});
    const data = await res.json();
    if (data.error) { out.innerHTML = '<div class="err">' + escapeHtml(data.error) + '</div>'; document.getElementById('agent-stop-btn').style.display = 'none'; return; }
    _currentRunId = data.run_id;
    streamAgentSteps(data.run_id);
}

function streamAgentSteps(run_id) {
    const out = document.getElementById('agent-output');
    const es = new EventSource('/api/agent/stream/' + run_id);
    es.onmessage = function(e) {
        try {
            const d = JSON.parse(e.data);
            if (d.done)  { es.close(); document.getElementById('agent-stop-btn').style.display = 'none'; return; }
            if (d.error) { out.innerHTML += '<div class="err">[error] ' + escapeHtml(d.error) + '</div>'; es.close(); document.getElementById('agent-stop-btn').style.display = 'none'; return; }
            const cls = d.type === 'thought' ? 'dim' : d.type === 'action' ? 'info' : d.type === 'result' ? 'warn' : '';
            out.innerHTML += '<div class="' + cls + '">[' + escapeHtml(d.type || '') + '] ' + escapeHtml(d.content || '') + '</div>';
            out.scrollTop = out.scrollHeight;
        } catch(err) {}
    };
}

async function stopHalTask() {
    if (_currentRunId) await fetch('/api/agent/stop/' + _currentRunId, {method:'POST'});
    document.getElementById('agent-stop-btn').style.display = 'none';
}
</script>
{% endblock %}
