#!/usr/bin/env python3
"""Generate HTML report from /tmp/tw_state.json, save to /root/.hermes/reports/"""
import json, os

with open('/tmp/tw_state.json') as f:
    state = json.load(f)

# Support both key names (old runs used 'date_str', new ones use 'date')
date = state.get('date') or state.get('date_str')
daily_charts = state['daily_charts']
weekly_charts = state['weekly_charts']
daily_colours = state['daily_colours']
weekly_colours = state['weekly_colours']
bull_d, bear_d = state['bull_d'], state['bear_d']
bull_w, bear_w = state['bull_w'], state['bear_w']

# Load TastyTrade positions if available
position_underlyings = []
if os.path.exists('/tmp/tt_positions.json'):
    with open('/tmp/tt_positions.json') as f:
        tt = json.load(f)
    position_underlyings = tt.get('underlyings', [])

colour_order = {'BLUE': 0, 'BLUE-GREEN': 1, 'GREEN': 2, 'TRIM-OPTION': 3, 'PINK': 4, 'PINK-RED': 5, 'RED': 6}
colour_hex = {
    'BLUE': '#3b82f6', 'BLUE-GREEN': '#06b6d4', 'GREEN': '#22c55e',
    'TRIM-OPTION': '#84cc16', 'PINK': '#f472b6', 'PINK-RED': '#e11d48', 'RED': '#ef4444',
}
colour_label = {
    'BLUE': '🔵 BLUE', 'BLUE-GREEN': '🔵🟢 BLUE-GREEN', 'GREEN': '🟢 GREEN',
    'TRIM-OPTION': '🌿 TRIM', 'PINK': '🩷 PINK', 'PINK-RED': '🩷🔴 PINK-RED', 'RED': '🔴 RED',
}

all_tickers = sorted(set(daily_colours) | set(weekly_colours))
sorted_tickers = sorted(all_tickers, key=lambda t: (colour_order.get(daily_colours.get(t), 99), t))

# Split into position tickers and rest
position_tickers = [t for t in sorted_tickers if t in position_underlyings]
other_tickers = [t for t in sorted_tickers if t not in position_underlyings]

def badge(colour):
    if not colour:
        return '<span style="color:#888">—</span>'
    return f'<span style="background:{colour_hex.get(colour,"#888")};color:white;padding:2px 8px;border-radius:4px;font-size:12px;font-weight:600;">{colour_label.get(colour, colour)}</span>'

def table_row(t, position=False):
    dc = daily_colours.get(t, '')
    wc = weekly_colours.get(t, '')
    pos_badge = '<span style="background:#7c3aed;color:white;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;margin-left:6px;">POS</span>' if position else ''
    return (
        f'<tr data-daily="{dc}" data-weekly="{wc}" data-ticker="{t}">'
        f'<td style="padding:6px 12px;font-weight:600;font-family:monospace;">'
        f'<a href="#chart-{t}" style="color:inherit;text-decoration:none;border-bottom:1px dashed #9ca3af;">{t}</a>{pos_badge}</td>'
        f'<td style="padding:6px 12px;">{badge(dc)}</td>'
        f'<td style="padding:6px 12px;">{badge(wc)}</td></tr>'
    )

# Position rows (always shown, no filter)
position_rows_html = ''.join(table_row(t, position=True) for t in position_tickers)

# Other rows (filterable)
other_rows_html = ''.join(table_row(t) for t in other_tickers)

# Chart sections — each card gets id="chart-TICKER"
sections = []
current_group = None
for ticker in sorted_tickers:
    dc = daily_colours.get(ticker)
    wc = weekly_colours.get(ticker)
    dimg = daily_charts.get(ticker, '')
    wimg = weekly_charts.get(ticker, '')
    group = colour_label.get(dc, '— No Daily Signal')
    if group != current_group:
        current_group = group
        hex_c = colour_hex.get(dc, '#444')
        sections.append(f'<h2 style="margin:40px 0 16px;padding:10px 16px;background:{hex_c};color:white;border-radius:6px;">{group}</h2>')
    is_pos = ticker in position_underlyings
    pos_indicator = '<span style="background:#7c3aed;color:white;padding:1px 6px;border-radius:4px;font-size:11px;font-weight:600;margin-left:8px;">IN POSITION</span>' if is_pos else ''
    daily_img_html = (f'<div style="flex:1;min-width:0;"><div style="font-size:11px;color:#666;margin-bottom:4px;">DAILY</div>'
        f'<img src="{dimg}" style="width:100%;border-radius:4px;border:1px solid #e5e7eb;cursor:zoom-in;" loading="lazy" onclick="openLightbox(this)"></div>') if dimg else '<div style="flex:1;color:#999;font-size:13px;">No daily chart</div>'
    weekly_img_html = (f'<div style="flex:1;min-width:0;"><div style="font-size:11px;color:#666;margin-bottom:4px;">WEEKLY</div>'
        f'<img src="{wimg}" style="width:100%;border-radius:4px;border:1px solid #e5e7eb;cursor:zoom-in;" loading="lazy" onclick="openLightbox(this)"></div>') if wimg else '<div style="flex:1;color:#999;font-size:13px;">No weekly chart</div>'
    border = 'border:2px solid #7c3aed;' if is_pos else ''
    sections.append(
        f'<div id="chart-{ticker}" style="margin-bottom:32px;padding:16px;background:#fff;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,0.1);{border}">'
        f'<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px;">'
        f'<span style="font-size:18px;font-weight:700;">{ticker}</span>{pos_indicator}{badge(dc)}<span style="color:#9ca3af;">→</span>{badge(wc)}</div>'
        f'<div style="display:flex;gap:16px;">{daily_img_html}{weekly_img_html}</div></div>'
    )

# Filter options (multi-select checkboxes)
colour_keys = ['BLUE', 'BLUE-GREEN', 'GREEN', 'TRIM-OPTION', 'PINK', 'PINK-RED', 'RED']

def build_checkbox_panel(dd_id, label):
    items = '\n'.join(
        f'    <label><input type="checkbox" value="{k}" onchange="updateBtn(\'{dd_id}\',\'{label}\');applyFilters()"> {colour_label[k]}</label>'
        for k in colour_keys
    )
    return f"""<div class="filter-dropdown" id="{dd_id}">
  <button class="filter-btn" onclick="toggleDD('{dd_id}');event.stopPropagation()">{label}: All ▾</button>
  <div class="filter-panel" style="display:none">
    <button class="filter-clear" onclick="clearDD('{dd_id}','{label}');applyFilters()">✕ Clear</button>
{items}
  </div>
</div>"""

daily_dd_html = build_checkbox_panel('dd-daily', 'Daily')
weekly_dd_html = build_checkbox_panel('dd-weekly', 'Weekly')

positions_section = ''
if position_tickers:
    positions_section = f"""
<h2 id="positions" style="display:flex;align-items:center;gap:10px;">
  <span>My Positions</span>
  <span style="background:#7c3aed;color:white;padding:2px 10px;border-radius:20px;font-size:13px;font-weight:600;">{len(position_tickers)}</span>
</h2>
<table>
  <thead><tr><th>Ticker</th><th>Daily</th><th>Weekly</th></tr></thead>
  <tbody>{position_rows_html}</tbody>
</table>"""

filter_js = """
function toggleDD(id) {
    var panel = document.getElementById(id).querySelector('.filter-panel');
    panel.style.display = panel.style.display === 'none' ? '' : 'none';
}
function getSelected(id) {
    return Array.from(document.querySelectorAll('#' + id + ' input[type="checkbox"]:checked')).map(function(cb){ return cb.value; });
}
function updateBtn(id, label) {
    var sel = getSelected(id);
    var btn = document.querySelector('#' + id + ' .filter-btn');
    btn.textContent = label + ': ' + (sel.length === 0 ? 'All' : sel.length + ' selected') + ' \u25be';
}
function clearDD(id, label) {
    document.querySelectorAll('#' + id + ' input[type="checkbox"]').forEach(function(cb){ cb.checked = false; });
    updateBtn(id, label);
}
function applyFilters() {
    var daily = getSelected('dd-daily');
    var weekly = getSelected('dd-weekly');
    var rows = document.querySelectorAll('#summary-tbody tr');
    var visible = 0;
    rows.forEach(function(row) {
        var rd = row.getAttribute('data-daily');
        var rw = row.getAttribute('data-weekly');
        var show = (daily.length === 0 || daily.indexOf(rd) !== -1) && (weekly.length === 0 || weekly.indexOf(rw) !== -1);
        row.style.display = show ? '' : 'none';
        if (show) visible++;
    });
    document.getElementById('filter-count').textContent = visible + ' ticker' + (visible !== 1 ? 's' : '');
}
document.addEventListener('click', function(e) {
    document.querySelectorAll('.filter-dropdown').forEach(function(dd) {
        if (!dd.contains(e.target)) dd.querySelector('.filter-panel').style.display = 'none';
    });
});
function downloadCSV() {
    var rows = document.querySelectorAll('#summary-tbody tr');
    var lines = ['Symbol'];
    rows.forEach(function(row) {
        if (row.style.display !== 'none') {
            lines.push(row.getAttribute('data-ticker'));
        }
    });
    var blob = new Blob([lines.join('\\n')], {type: 'text/csv'});
    var a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'tickers.csv';
    a.click();
}
"""

html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>TradeWhisperer \u2014 {date}</title>
<style>
body{{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#f3f4f6;margin:0;padding:0;}}
.container{{max-width:1100px;margin:0 auto;padding:24px;}}
.stats{{display:flex;gap:16px;margin-bottom:32px;flex-wrap:wrap;}}
.stat{{background:#fff;border-radius:8px;padding:16px 24px;box-shadow:0 1px 3px rgba(0,0,0,0.1);}}
.stat-label{{font-size:12px;color:#6b7280;text-transform:uppercase;letter-spacing:.05em;}}
.stat-value{{font-size:22px;font-weight:700;margin-top:4px;}}
table{{width:100%;border-collapse:collapse;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,0.1);margin-bottom:40px;}}
th{{background:#111;color:white;padding:10px 12px;text-align:left;font-size:12px;text-transform:uppercase;}}
tr:nth-child(even){{background:#f9fafb;}}
tr[style*="display: none"] + tr, tr[style*="display:none"] + tr {{background:#fff;}}
.nav{{position:sticky;top:0;background:#111;color:white;padding:12px 24px;z-index:100;display:flex;align-items:center;gap:16px;}}
.nav a{{color:#d1d5db;text-decoration:none;font-size:13px;}}
.filters{{display:flex;align-items:center;gap:12px;margin-bottom:12px;flex-wrap:wrap;}}
.filter-dropdown{{position:relative;}}
.filter-btn{{padding:6px 12px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;background:#fff;cursor:pointer;font-weight:600;color:#374151;white-space:nowrap;}}
.filter-btn:hover{{border-color:#3b82f6;}}
.filter-panel{{position:absolute;top:calc(100% + 4px);left:0;background:#fff;border:1px solid #d1d5db;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,0.12);padding:8px;z-index:200;min-width:160px;display:flex;flex-direction:column;gap:4px;}}
.filter-panel label{{display:flex;align-items:center;gap:8px;font-size:13px;padding:4px 6px;border-radius:4px;cursor:pointer;white-space:nowrap;}}
.filter-panel label:hover{{background:#f3f4f6;}}
.filter-clear{{font-size:12px;color:#ef4444;background:none;border:none;cursor:pointer;text-align:left;padding:2px 6px;margin-bottom:2px;}}
.download-btn{{padding:6px 12px;border:1px solid #3b82f6;border-radius:6px;font-size:13px;background:#eff6ff;color:#1d4ed8;cursor:pointer;font-weight:600;white-space:nowrap;}}
.download-btn:hover{{background:#dbeafe;}}
#filter-count{{font-size:13px;color:#6b7280;margin-left:4px;}}
</style>
</head>
<body>
<div class="nav">
  <span style="font-weight:700;">\U0001f4ca TradeWhisperer \u2014 {date}</span>
  <a href="#positions">Positions</a>
  <a href="#summary">All Tickers</a>
  <a href="#charts">Charts</a>
</div>
<div class="container">
<h1>\U0001f4ca TradeWhisperer</h1>
<p style="color:#6b7280;">{date} \u00b7 Daily &amp; Weekly Smart Candle Colours</p>
<div class="stats">
  <div class="stat"><div class="stat-label">Daily Bullish</div><div class="stat-value" style="color:#22c55e;">{bull_d}</div></div>
  <div class="stat"><div class="stat-label">Daily Bearish</div><div class="stat-value" style="color:#ef4444;">{bear_d}</div></div>
  <div class="stat"><div class="stat-label">Weekly Bullish</div><div class="stat-value" style="color:#22c55e;">{bull_w}</div></div>
  <div class="stat"><div class="stat-label">Weekly Bearish</div><div class="stat-value" style="color:#ef4444;">{bear_w}</div></div>
  <div class="stat"><div class="stat-label">Tickers</div><div class="stat-value">{len(sorted_tickers)}</div></div>
</div>

{positions_section}

<h2 id="summary">All Tickers</h2>
<div class="filters">
  {daily_dd_html}
  {weekly_dd_html}
  <span id="filter-count">{len(other_tickers)} tickers</span>
  <button class="download-btn" onclick="downloadCSV()">⬇ CSV</button>
</div>
<table>
  <thead><tr><th>Ticker</th><th>Daily</th><th>Weekly</th></tr></thead>
  <tbody id="summary-tbody">{other_rows_html}</tbody>
</table>

<h2 id="charts">Charts</h2>
{''.join(sections)}
<p style="color:#9ca3af;font-size:12px;text-align:center;margin-top:40px;">Generated by Hermes \u00b7 Not financial advice \u00b7 Images \u00a9 TradeWhisperer</p>
</div>
<script>{filter_js}
function openLightbox(img) {{
    var lb = document.getElementById('lightbox');
    var lbImg = document.getElementById('lightbox-img');
    lbImg.src = img.src;
    lb.style.display = 'flex';
    document.body.style.overflow = 'hidden';
}}
function closeLightbox() {{
    document.getElementById('lightbox').style.display = 'none';
    document.body.style.overflow = '';
}}
document.addEventListener('keydown', function(e) {{ if (e.key === 'Escape') closeLightbox(); }});
</script>
<div id="lightbox" onclick="closeLightbox()" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,0.85);z-index:1000;align-items:center;justify-content:center;cursor:zoom-out;">
  <img id="lightbox-img" src="" style="max-width:95vw;max-height:95vh;border-radius:6px;box-shadow:0 8px 40px rgba(0,0,0,0.6);object-fit:contain;">
</div>
</body>
</html>"""

report_path = f"/root/.hermes/reports/tw_report_{date}.html"
with open(report_path, 'w') as f:
    f.write(html)
print(f"HTML saved: {report_path} ({len(html):,} chars)")
