#!/usr/bin/env python3
import cgi, sys
sys.path.insert(0, '/opt/ngon/apps')
from managers.auth_manager import AuthManager, generate_login_page_html

_form = cgi.FieldStorage()
_auth = AuthManager('how_to_remote_start')
_auth_required, _should_exit, _headers = _auth.require_auth(_form)

if _should_exit:
    print("Content-Type: application/json")
    if _headers:
        print(_headers)
    print("")
    if _auth_required:
        print('{"success": false, "error": "Authentication required"}')
    else:
        print('{"success": true}')
    sys.exit(0)

if _auth_required:
    print("Content-Type: text/html")
    print("")
    print(generate_login_page_html("How-To: Remote Gen Start"))
    sys.exit(0)


sys.path.insert(0, '/var/www/html/ngon')
from links import generate_dropdown_html, generate_dropdown_css, generate_dropdown_js
_user_access = AuthManager.get_user_access()
_nav_html = generate_dropdown_html(_user_access)
_nav_css = generate_dropdown_css()
_nav_js = generate_dropdown_js()

print("Content-Type: text/html\n")

HTML = """<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NGON How-To: Remote Gen Start</title>
<link rel="stylesheet" href="/status/styles.css?v=30" />
<style>__NAV_CSS__</style>
<style>
html, body { background: #1a1a1a !important; }
body { padding-bottom: 60px; }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: #666; border-radius: 3px; }

.header {
    background-color: rgba(255,255,255,0.05) !important;
    border-radius: 8px !important;
    padding: 30px !important;
    margin: 20px !important;
    border: 1px solid rgba(255,255,255,0.1) !important;
    border-bottom: none !important;
    display: flex !important;
    justify-content: space-between !important;
    align-items: flex-start !important;
}
.header h1.dropdown-title {
    font-size: 2.2em !important;
    font-weight: 600 !important;
    margin: 3px 0 0 0 !important;
    line-height: 1.2 !important;
}

.howto-body { max-width: 900px; margin: 0 auto; padding: 20px; }

h2 {
    font-size: 22px;
    color: #00ff00;
    margin: 40px 0 14px 0;
    padding-bottom: 8px;
    border-bottom: 1px solid #333;
}
h3 { font-size: 17px; color: #4a9eff; margin: 24px 0 10px 0; }
h4 { font-size: 15px; color: #ffaa00; margin: 18px 0 8px 0; }
p { margin: 10px 0; color: #ccc; }
ul, ol { margin: 10px 0 10px 24px; color: #ccc; }
li { margin: 6px 0; }
code {
    background: #2a2a2a;
    padding: 2px 6px;
    border-radius: 3px;
    font-family: 'Menlo', 'Consolas', monospace;
    font-size: 13px;
    color: #ffaa00;
}

.toc {
    background: #222;
    border: 1px solid #333;
    border-radius: 6px;
    padding: 16px 20px;
    margin: 20px 0;
}
.toc h3 { color: #e0e0e0; margin-top: 0; font-size: 14px; text-transform: uppercase; letter-spacing: 1px; }
.toc ul { list-style: none; margin: 10px 0 0 0; }
.toc li { margin: 4px 0; }
.toc a { color: #4a9eff; text-decoration: none; }
.toc a:hover { color: #00ff00; }

.cheat {
    background: #1e2a1e;
    border: 1px solid #2a4a2a;
    border-radius: 6px;
    padding: 18px 22px;
    margin: 20px 0;
}
.cheat h3 { color: #00ff00; margin-top: 0; }
.cheat table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 14px; }
.cheat th, .cheat td { padding: 8px 10px; text-align: left; border-bottom: 1px solid #2a4a2a; vertical-align: top; }
.cheat th { color: #00ff00; font-weight: 600; }
.cheat td { color: #ccc; }

.callout {
    border-left: 3px solid #4a9eff;
    background: #1e232a;
    padding: 12px 16px;
    margin: 16px 0;
    border-radius: 0 4px 4px 0;
}
.callout.warn { border-left-color: #ff6600; background: #2a1f12; }
.callout.bad  { border-left-color: #ff4444; background: #2a1414; }
.callout.good { border-left-color: #00ff00; background: #122a12; }
.callout .label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    display: block;
    margin-bottom: 4px;
}
.callout.warn .label { color: #ff6600; }
.callout.bad  .label { color: #ff4444; }
.callout.good .label { color: #00ff00; }
.callout p { margin: 4px 0; }

.flow {
    background: #181818;
    border: 1px solid #333;
    border-radius: 6px;
    padding: 14px 18px;
    margin: 14px 0;
    font-family: 'Menlo', 'Consolas', monospace;
    font-size: 13px;
    color: #ccc;
    white-space: pre-wrap;
    line-height: 1.65;
}
.flow .step { color: #4a9eff; }
.flow .action { color: #00ff00; }
.flow .warn { color: #ff6600; }

.tag {
    display: inline-block;
    background: #2a2a2a;
    color: #4a9eff;
    padding: 2px 8px;
    border-radius: 3px;
    font-size: 12px;
    font-family: monospace;
    margin: 0 2px;
}
.btn-name { color: #00ff00; font-weight: 600; }

@media (max-width: 700px) {
    .howto-body { padding: 14px; }
    h2 { font-size: 19px; }
    h3 { font-size: 15px; }
    .cheat table { font-size: 12px; }
    .cheat th, .cheat td { padding: 6px 4px; }
}
</style>
</head>
<body>

<div class="header">
    <div>
      <div class="dropdown">
        <h1 class="dropdown-title">NGON Mining - How-To: Remote Gen Start</h1>
        <div class="dropdown-content">__DROPDOWN_HTML__</div>
      </div>
    </div>
</div>

<div class="howto-body">

<p>This page covers <strong>remote generator control</strong> from the status
page — putting a gen in Manual, clearing alarms, starting it, and closing its
breaker (On&nbsp;Load), plus the group-level versions. These commands write
directly to the generator's DSE controller over the network, so they move real
iron. Read the safety section before you use them.</p>

<div class="callout bad">
<span class="label">These are physical actions on a running-capable machine</span>
<p>Start and On&nbsp;Load crank an engine and close a breaker. <strong>Never</strong>
send them unless you know the gen is clear, no one is working on or near it, and
you've got eyes on it (in person or on camera). The system asks you to confirm
this for a reason.</p>
</div>

<div class="toc">
    <h3>Contents</h3>
    <ul>
        <li><a href="#cheat">Quick Cheat Sheet</a></li>
        <li><a href="#access">Who Can Do This</a></li>
        <li><a href="#actions">The Four Gen Actions</a></li>
        <li><a href="#interlocks">Interlocks — Why a Button Is Greyed Out</a></li>
        <li><a href="#single">Starting One Gen (step by step)</a></li>
        <li><a href="#group">Group Control (Reset / Restart / On Load)</a></li>
        <li><a href="#trouble">When It Won't Work</a></li>
        <li><a href="#safety">Safety Rules</a></li>
    </ul>
</div>

<!-- ============================================================ -->
<h2 id="cheat">Quick Cheat Sheet</h2>

<div class="cheat">
<h3>The four per-gen actions</h3>
<table>
<tr><th>Button</th><th>What it does</th><th>Needs</th></tr>
<tr><td><span class="btn-name">Set Manual Mode</span></td>
    <td>Switches the DSE controller to Manual so it will accept a start command. Safe — cannot start the engine by itself.</td>
    <td>Always allowed</td></tr>
<tr><td><span class="btn-name">Clear Alarms</span></td>
    <td>Resets the gen's resettable fault codes. Safe — does not start anything.</td>
    <td>Always allowed</td></tr>
<tr><td><span class="btn-name">Start Gen</span></td>
    <td>Cranks and starts the engine.</td>
    <td>Manual mode, no active shutdown alarm, gen not already running</td></tr>
<tr><td><span class="btn-name">On Load</span></td>
    <td>Closes the gen breaker so it picks up load.</td>
    <td>Gen running</td></tr>
</table>
</div>

<div class="cheat">
<h3>The usual sequence to bring a stopped gen up</h3>
<table>
<tr><th>Step</th><th>Do</th></tr>
<tr><td>1</td><td><span class="btn-name">Set Manual Mode</span></td></tr>
<tr><td>2</td><td><span class="btn-name">Clear Alarms</span> (if any are showing)</td></tr>
<tr><td>3</td><td><span class="btn-name">Start Gen</span> — confirm the eyes-on prompt</td></tr>
<tr><td>4</td><td>Let it warm up &amp; stabilize, then <span class="btn-name">On Load</span> to pick up miners</td></tr>
</table>
</div>

<!-- ============================================================ -->
<h2 id="access">Who Can Do This</h2>

<p>Remote gen control is a separate permission (<code>gen_control</code>). If
you don't have it, the Gen Control option and the group buttons simply don't
appear for you — there's nothing to click. Ask a lead to grant it in Site
Manager if you need it.</p>

<p>The permission is enforced on the server, not just hidden in the page, so it
can't be worked around. Every action you send is written to
<code>gen_control.log</code> and pushed to that site's alert channel with your
name on it.</p>

<!-- ============================================================ -->
<h2 id="actions">The Four Gen Actions</h2>

<p><strong>Where:</strong> on the status page, click a generator → in the action
picker choose <span class="btn-name">Gen Control</span>. The modal opens showing
that gen's live state — its <em>mode</em> (Auto/Manual), whether it's
<em>running</em> (with RPM), and its <em>alarm</em> state — then the four
buttons below.</p>

<h3>Set Manual Mode</h3>
<p>Puts the DSE controller in Manual. This is the mode a gen must be in before
it will accept a remote Start. Setting Manual by itself does nothing to the
engine — it's just flipping the key position. Always allowed.</p>

<h3>Clear Alarms</h3>
<p>Sends the controller's "reset resettable alarms" command, clearing fault
codes that have been resolved. Always allowed and can't start the engine. If a
gen has a <em>shutdown</em>-class alarm, you'll need to clear it before Start
will unlock (assuming the underlying fault is actually fixed).</p>

<div class="callout warn">
<span class="label">Clearing an alarm doesn't fix the problem</span>
<p>Clear Alarms only tells the controller to drop the fault flag. If the real
issue is still there (low coolant, low oil, high temp), the gen will just fault
again — possibly after it's already running. Clear alarms because you've
addressed the cause, not to force past a warning.</p>
</div>

<h3>Start Gen</h3>
<p>Cranks the engine. Only unlocks when the gen is in Manual, has no active
shutdown alarm, and isn't already running. When you click it you get an
eyes-on confirmation dialog — you have to type <code>yes</code> to proceed. It
asks the questions that matter: is the gen clear, are you watching it, is
anyone near it.</p>

<h3>On Load</h3>
<p>Closes the gen's breaker so it starts carrying electrical load (the miners).
Only available once the gen is running. Closing a breaker onto load causes an
inrush — at group level the system fires On&nbsp;Load across gens together to
balance it (see Group Control).</p>

<!-- ============================================================ -->
<h2 id="interlocks">Interlocks — Why a Button Is Greyed Out</h2>

<p>The buttons enable/disable themselves based on the gen's live state, and the
server double-checks every command. If a button is greyed out, the gen isn't in
a state where that action is safe:</p>

<div class="cheat">
<table>
<tr><th>Button greyed out</th><th>Because</th><th>Fix</th></tr>
<tr><td><span class="btn-name">Start Gen</span></td>
    <td>Gen isn't in Manual</td><td>Set Manual Mode first</td></tr>
<tr><td><span class="btn-name">Start Gen</span></td>
    <td>Active shutdown alarm</td><td>Resolve the fault, then Clear Alarms</td></tr>
<tr><td><span class="btn-name">Start Gen</span></td>
    <td>Gen already running</td><td>Nothing to do — it's up</td></tr>
<tr><td><span class="btn-name">On Load</span></td>
    <td>Gen not running</td><td>Start it first, let it stabilize</td></tr>
</table>
</div>

<div class="callout">
<span class="label">The server has the final say</span>
<p>Even if the page let you click something, the API re-checks these interlocks
and refuses anything unsafe — it will not write a Start to a gen with a
shutdown alarm, for example. The greyed-out buttons just mirror those same
rules so you see them up front.</p>
</div>

<!-- ============================================================ -->
<h2 id="single">Starting One Gen (step by step)</h2>

<div class="flow"><span class="step">1.</span> Confirm the gen is physically clear and safe. Eyes on it — in person or camera.
<span class="step">2.</span> Status page → click the gen → <span class="action">Gen Control</span>.
<span class="step">3.</span> Read the live pills at the top: mode, running/stopped, alarm state.
<span class="step">4.</span> <span class="action">Set Manual Mode.</span> The pill should flip to Manual.
<span class="step">5.</span> If any alarm is showing (and you've addressed the cause): <span class="action">Clear Alarms.</span>
<span class="step">6.</span> <span class="action">Start Gen.</span> Type <span class="warn">yes</span> at the eyes-on prompt.
<span class="step">7.</span> Watch it crank and come up to RPM. Let it warm up and stabilize.
<span class="step">8.</span> When it's steady, <span class="action">On Load</span> to close the breaker and pick up miners.
<span class="step">9.</span> If the group was auto-slept, Auto-Wake will ramp miners back on the newly-available capacity (see the Power Management guide).</div>

<div class="callout good">
<span class="label">You usually don't have to touch the miners</span>
<p>Once the gen is up and on load, the power system's Auto-Wake handles bringing
miners back gradually. Don't force-wake unless you've verified the gen is solid
and need it back faster.</p>
</div>

<!-- ============================================================ -->
<h2 id="group">Group Control (Reset / Restart / On Load)</h2>

<p>When a whole gen group is down or all up, a single contextual
<strong>group button</strong> appears on the group header (gen-control users
only). It figures out the right action from the group's live state and applies
it to every eligible gen at once. Only <em>active</em> and <em>active-swap</em>
gens are touched; operator-disabled gens are skipped.</p>

<div class="cheat">
<table>
<tr><th>Button</th><th>Appears when</th><th>What it does</th></tr>
<tr><td><span class="btn-name">Reset Group</span></td>
    <td>All gens down, not yet in Manual/cleared</td>
    <td>Sets every gen to Manual and clears alarms — prepping them to start</td></tr>
<tr><td><span class="btn-name">Restart Group</span></td>
    <td>All gens down and already Manual/cleared</td>
    <td>Starts the gens, <strong>staggered ~5 s apart</strong> so they don't all crank at once</td></tr>
<tr><td><span class="btn-name">On Load Group</span></td>
    <td>All gens running but not loaded</td>
    <td>Closes all breakers together to balance the inrush across gens</td></tr>
</table>
</div>

<div class="callout warn">
<span class="label">Whole-group, all-or-nothing</span>
<p>Group actions require <em>every</em> eligible gen in the group to be
reachable. If even one gen's controller is unreachable, the whole group button
hides and the action won't fire — there are no partial group operations. That's
deliberate: a half-started group is worse than none. If the button's missing,
one gen is likely offline to control; handle it individually or fix the comms.</p>
</div>

<p><strong>Restart Group</strong> also gives you the same type-<code>yes</code>
eyes-on confirmation as a single start, since it's cranking multiple engines.</p>

<!-- ============================================================ -->
<h2 id="trouble">When It Won't Work</h2>

<ul>
<li><strong>"Controller unreachable"</strong> — the gen has no live bridge
connection right now (its collector isn't seeing it), so no command can be
written. Check the gen's network/bridge before trying again.</li>
<li><strong>Start stays greyed</strong> — walk the interlocks table above: not
Manual, active shutdown alarm, or already running.</li>
<li><strong>Group button isn't there</strong> — either you don't have
gen-control access, or one eligible gen in the group is unreachable (whole-group
rule), or the group isn't in a state that has a group action (e.g. mixed
up/down).</li>
<li><strong>You cleared the alarm but it came back</strong> — the underlying
fault is still active. Don't keep clearing; get the gen looked at.</li>
</ul>

<!-- ============================================================ -->
<h2 id="safety">Safety Rules</h2>

<div class="callout bad">
<span class="label">Before any Start or On Load</span>
<ul>
<li>Confirm the gen is <strong>clear</strong> — no tools, no covers off, nothing
in the way of the engine or breaker.</li>
<li>Confirm <strong>no one is working on or near</strong> the gen.</li>
<li>Have <strong>eyes on it</strong> — physically present or on a live camera.</li>
<li>Resolve faults <em>before</em> clearing them. Clearing an alarm to force a
start on an unfixed fault can damage the gen.</li>
</ul>
</div>

<div class="callout">
<span class="label">Everything is logged</span>
<p>Every remote action records your name, the gen, and the action to
<code>gen_control.log</code> and posts to the site's alert channel. This isn't
about blame — it's so the team can see what happened to a gen and when, which
matters when you're diagnosing a trip later.</p>
</div>

<div class="callout good">
<span class="label">When in doubt, Manual + Clear are the safe ones</span>
<p>Set Manual Mode and Clear Alarms can't start an engine and are always
allowed. If you're just prepping a gen or resetting a nuisance fault, those two
are risk-free. It's Start and On&nbsp;Load that move iron — treat them with
respect.</p>
</div>

</div>

<script>__DROPDOWN_JS__</script>
</body>
</html>
"""

HTML = HTML.replace("__NAV_CSS__", _nav_css)
HTML = HTML.replace("__DROPDOWN_CSS__", "")
HTML = HTML.replace("__DROPDOWN_HTML__", _nav_html)
HTML = HTML.replace("__DROPDOWN_JS__", _nav_js)

print(HTML)
