import json
import math
from typing import Any, Optional
from IPython.display import HTML, display

STYLE = """
<style>
/* ── Slate / Dark Navy Theme (Image Reference + Material 16 Feel) ── */
.eco-slate {
  --bg-app: transparent;
  --bg-card: #15181e;
  --bg-tip: #1e222a;
  --bg-hover: #262b35;
  --border-subtle: #2b303b;
  
  --text-main: #e2e8f0;
  --text-muted: #94a3b8;
  --text-highlight: #f8fafc;
  
  --color-green-bg: #103422;
  --color-green-text: #4ade80;
  
  --color-red: #f87171;
  --color-yellow: #fbbf24;
  --color-blue: #60a5fa;

  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--text-main);
  font-size: 13px;
  line-height: 1.5;
  margin: 6px 0;
}

@media (prefers-color-scheme: light) {
  .eco-slate {
    --bg-card: #ffffff;
    --bg-tip: #f1f5f9;
    --bg-hover: #e2e8f0;
    --border-subtle: #cbd5e1;
    
    --text-main: #334155;
    --text-muted: #64748b;
    --text-highlight: #0f172a;
    
    --color-green-bg: #dcfce7;
    --color-green-text: #16a34a;
    
    --color-red: #ef4444;
    --color-yellow: #d97706;
    --color-blue: #2563eb;
  }
}

.eco-slate * { box-sizing: border-box; }

/* ── Typography & Icons ── */
.eco-icon { display: inline-block; width: 16px; text-align: center; margin-right: 6px; font-style: normal; }

/* ── 1. Collapsed Pill View ── */
.eco-slate-pill {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--bg-card); border: 1px solid var(--border-subtle);
  padding: 6px 12px; border-radius: 20px;
  cursor: pointer; transition: all 0.2s cubic-bezier(0.2, 0, 0, 1);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  font-weight: 500; font-size: 13px; user-select: none;
}
.eco-slate-pill:hover { background: var(--bg-tip); transform: scale(0.98); }

.eco-shield-badge {
  background: var(--color-green-bg); color: var(--color-green-text);
  padding: 2px 8px; border-radius: 12px; font-weight: 600; font-size: 12px;
  display: inline-flex; align-items: center; gap: 4px;
}
.eco-shield-badge.mod { background: #422006; color: var(--color-yellow); }
.eco-shield-badge.hvy { background: #450a0a; color: var(--color-red); }

@media (prefers-color-scheme: light) {
  .eco-shield-badge.mod { background: #fef3c7; color: var(--color-yellow); }
  .eco-shield-badge.hvy { background: #fee2e2; color: var(--color-red); }
}

/* ── 2. Expanded Detail Card ── */
.eco-slate-card {
  display: none; margin-top: 10px; background: var(--bg-card);
  border: 1px solid var(--border-subtle); border-radius: 20px;
  padding: 18px; width: 340px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.25);
  animation: ecoSlateIn 0.25s cubic-bezier(0.2, 0, 0, 1) forwards;
  transform-origin: top left;
}
@keyframes ecoSlateIn { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }

/* Header */
.eco-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.eco-card-title { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: 6px; color: var(--text-highlight); }
.eco-info-btn { 
  background: var(--bg-tip); border: 1px solid var(--border-subtle); color: var(--text-muted);
  width: 30px; height: 30px; border-radius: 15px; font-size: 14px; font-weight: 500; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: all 0.2s;
}
.eco-info-btn:hover { background: var(--bg-hover); color: var(--text-main); }

/* Main Metric */
.eco-main-metric { font-size: 18px; font-weight: 600; color: var(--text-highlight); margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }

/* List Details */
.eco-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 18px; font-size: 13px; color: var(--text-muted); }
.eco-list-item { display: flex; align-items: flex-start; }
.eco-list-item strong { color: var(--text-highlight); font-weight: 500; }

.eco-status-high { color: var(--color-red); font-weight: 500; }
.eco-status-normal { color: var(--color-green-text); font-weight: 500; }
.eco-status-under { color: var(--text-muted); font-weight: 500; }

/* Tip Box */
.eco-tip-box { background: var(--bg-tip); border-radius: 16px; padding: 14px; margin-bottom: 0; }
.eco-tip-header { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--color-green-text); margin-bottom: 8px; }
.eco-tip-text { font-size: 13px; color: var(--text-muted); line-height: 1.4; margin-bottom: 14px; }
.eco-tip-error { color: var(--color-red); font-weight: 500; margin-bottom: 6px; }

/* Action Buttons */
.eco-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.eco-btn-outline { 
  background: transparent; border: 1px solid var(--border-subtle); color: var(--text-muted);
  padding: 8px 14px; border-radius: 12px; font-size: 12px; font-weight: 500; cursor: pointer; transition: 0.2s;
}
.eco-btn-outline:hover { background: var(--bg-hover); color: var(--text-highlight); border-color: var(--text-muted); }
.eco-btn-filled { 
  background: var(--color-green-bg); border: 1px solid var(--color-green-bg); color: var(--color-green-text);
  padding: 8px 14px; border-radius: 12px; font-size: 12px; font-weight: 600; cursor: pointer; transition: 0.2s;
}
.eco-btn-filled:hover { filter: brightness(1.2); transform: scale(0.98); }

/* ── 3. Info Modal / Sheet ── */
.eco-info-sheet {
  display: none; 
  position: absolute; 
  top: 0; 
  left: 0; /* Changed from 350px to prevent clipping */
  background: var(--bg-card); 
  border: 1px solid var(--border-subtle); 
  border-radius: 20px;
  padding: 20px; 
  width: 100%; /* Take full width of parent */
  height: 100%; /* Take full height */
  box-sizing: border-box;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
  animation: ecoSlateIn 0.2s ease forwards; 
  z-index: 50; /* Bring above everything else */
}
.eco-info-sheet.open { display: block; }

/* Sparkline SVG Graph */
.eco-graph-container {
  background: var(--bg-card);
  border: 1px solid var(--border-subtle);
  border-radius: 12px;
  padding: 12px;
  margin-top: 12px;
  margin-bottom: 24px;
}
.eco-graph-svg {
  width: 100%;
  height: 60px;
  overflow: visible;
}
.eco-graph-axis { stroke: var(--bg-hover); stroke-width: 1; }
.eco-graph-label { fill: var(--text-muted); font-size: 9px; font-family: monospace; }

/* Container */
.eco-card-container { display: flex; position: relative; gap: 10px; align-items: flex-start; }
</style>

<script>
try {
  if (typeof window !== 'undefined') {
    window._ecoUI = {
      toggle: function(id) {
        const el = document.getElementById(id);
        if(el) el.style.display = (el.style.display === 'block') ? 'none' : 'block';
      },
      openSheet: function(id) {
        document.querySelectorAll('.eco-info-sheet').forEach(s => s.classList.remove('open')); // close others
        const el = document.getElementById(id);
        if(el) el.classList.add('open');
      },
      closeSheet: function(id) {
        const el = document.getElementById(id);
        if(el) el.classList.remove('open');
      }
    };
  }
} catch (e) {
  console.error("EcoML UI Script Error:", e);
}
</script>
"""

def _fmt(x: Any, d: int = 3) -> str:
    try: return f"{float(x):.{d}f}"
    except: return "—"

def _human_energy(kwh: float) -> str:
    wh = kwh * 1000.0
    if wh < 1.0: return f"{wh * 1000.0:.1f}mWh"
    return f"{wh:.2f}Wh"

class CellHook:
    def __init__(self, tracker, recommender: Optional[Any] = None):
        self.tracker = tracker
        self.recommender = recommender
        self.cell_history = {}

    def register(self):
        from IPython import get_ipython
        sh = get_ipython()
        if not sh:
            print("⚠ Not inside IPython – UI disabled")
            return
        sh.events.register("pre_run_cell", self._pre)
        sh.events.register("post_run_cell", self._post)
        print("EcoML UI CellHook Registered ✓")

    def _pre(self, *_):
        try: self.tracker.start_cell()
        except: pass

    def _post(self, result):
        code = getattr(result.info, "raw_cell", None)
        error = result.error_in_exec or getattr(result, "error_before_exec", None)

        try:
            rec = self.tracker.end_cell(recommender=self.recommender, error=error, code=code)
        except Exception as e:
            display(HTML(f"<div style='color:#ef4444;font-family:monospace;font-size:12px'>EcoML Tracking Error: {e}</div>"))
            return

        if not rec: return

        # Extract data
        cid        = int(rec.get("cell_id", 0))
        cell_id    = getattr(result.info, "cell_id", str(cid))
        score      = int(rec.get("score", 100))
        runtime    = float(rec.get("runtime_sec", 0) or 0)
        co2        = float(rec.get("co2_g", 0) or 0)
        energy_kwh = float(rec.get("energy_kwh", 0) or 0)
        
        co2_red, run_imp, enr_sav = 0, 0, 0
        baseline = self.cell_history.get(cell_id)
        if baseline and not error:
            co2_red = max(0, int(round((baseline['co2'] - co2) / max(0.0001, baseline['co2']) * 100)))
            run_imp = max(0, int(round((baseline['run'] - runtime) / max(0.0001, baseline['run']) * 100)))
            enr_sav = max(0, int(round((baseline['enr'] - energy_kwh) / max(0.0001, baseline['enr']) * 100)))
        elif not error and runtime > 0.05:
            self.cell_history[cell_id] = {'co2': co2, 'run': runtime, 'enr': energy_kwh}
        
        cpu        = float(rec.get("cpu_util_avg", 0) or 0)
        gpu        = float(rec.get("gpu_util_avg", 0) or 0)
        cpu_temp   = float(rec.get("cpu_temp_c", 0) or 0)
        gpu_temp   = float(rec.get("gpu_temp_c", 0) or 0)
        ram_pct    = float(rec.get("ram_used_pct", 0) or 0)
        
        cmp        = rec.get("comparison", {})
        reasons_r  = rec.get("recommended_reasons", [])
        eco_fix_before = rec.get("eco_fix_before")
        eco_fix_after  = rec.get("eco_fix_after")
        
        if isinstance(reasons_r, str):
            reasons_list = reasons_r.split(" | ")
        else:
            reasons_list = reasons_r

        # Gamification Score
        score = 100.0
        score -= min(20, cpu * 0.20)
        score -= min(20, gpu * 0.20)
        score -= min(15, max(0, max(gpu_temp, cpu_temp) - 70))
        if runtime > 1: score -= min(15, math.log(runtime) * 3)
        score = int(max(0, min(100, score)))

        # Status Tones
        if score >= 85 and co2 < 0.1:
            title = "Low Impact"
            badge_cls = ""
        elif score >= 50 and co2 < 0.5:
            title = "Moderate Impact"
            badge_cls = "mod"
        else:
            title = "High Energy Usage"
            badge_cls = "hvy"

        # Hardware Stress Logic
        if cpu > 80: cpu_txt = f"<span class='eco-status-high'>{_fmt(cpu, 0)}% (High)</span>"
        elif cpu < 20: cpu_txt = f"<span class='eco-status-under'>{_fmt(cpu, 0)}% (Underused)</span>"
        else: cpu_txt = f"<span class='eco-status-normal'>{_fmt(cpu, 0)}% (Normal)</span>"

        if gpu > 80: gpu_txt = f"<span class='eco-status-high'>{_fmt(gpu, 0)}% (High)</span>"
        elif gpu < 20: gpu_txt = f"<span class='eco-status-under'>{_fmt(gpu, 0)}% (Underused)</span>"
        else: gpu_txt = f"<span class='eco-status-normal'>{_fmt(gpu, 0)}% (Normal)</span>"

        # Separate Gemini errors from normal insights
        err_msg = ""
        opt_msg = ""
        for r in reasons_list:
            if not r: continue
            # Only route to err_msg for actual ❌ code errors — NOT for 🌱 eco suggestions
            if "❌" in r and "🌱" not in r:
                err_msg += r + "<br>"
            else:
                if opt_msg: opt_msg += "<br>"
                opt_msg += r

        # Component Strings
        card_id = f"eco-slate-card-{cid}"
        info_id = f"eco-slate-info-{cid}"
        fix_id  = f"eco-slate-fix-{cid}"

        # Determine if we should show the Tip Box immediately
        show_tip = (score < 80) or bool(err_msg) or bool(cmp) or bool(eco_fix_before)

        # Tip Box / Actions Build
        action_btns = []
        # Updated >= 0 threshold to ensure button renders
        if cmp and float(cmp.get("co2_saved_pct", 0.0)) >= 0:
            action_btns.append(f"<button class='eco-btn-filled' onclick=\"window._ecoUI.openSheet('{info_id}')\">⚖️ Compare CPU vs GPU</button>")
            
        if eco_fix_before and eco_fix_after:
            action_btns.append(f"<button class='eco-btn-filled' style='background:rgba(16,185,129,0.15); color:var(--color-green-text); border:1px solid rgba(16,185,129,0.3); font-weight:600;' onclick=\"window._ecoUI.openSheet('{fix_id}')\">⚡ Apply Eco Fix</button>")

        action_btns_html = " ".join(action_btns)

        tip_html = ""
        if show_tip:
            content_html = ""
            if opt_msg:
                content_html += f"<div>{opt_msg}</div>"
            if err_msg:
                content_html += f"<div class='eco-tip-error'>{err_msg}</div>"
            if not content_html:
                content_html = "Code executed successfully with minimal impact."
                
            tip_html = f"""
            <div class='eco-tip-box'>
              <div class='eco-tip-header'>💡 Optimization Tip</div>
              <div class='eco-tip-text'>{content_html}</div>
              <div class='eco-actions' style='flex-wrap: wrap;'>
                {action_btns_html if action_btns_html else "<button class='eco-btn-outline' style='color:var(--color-green-text);border-color:var(--color-green-text)'>✅ Already Optimized</button>"}
                <button class='eco-btn-outline' onclick="window._ecoUI.toggle('{card_id}')">Close</button>
              </div>
            </div>
            """
        else:
            if co2_red > 0 or run_imp > 0 or enr_sav > 0:
                tip_html = f"""
                <div style="background:rgba(16,185,129,0.05); border:1px solid rgba(16,185,129,0.2); border-radius:12px; padding:16px; margin-bottom:14px;">
                  <div style="font-weight:600; font-size:14px; color:var(--color-green-text); margin-bottom:14px; display:flex; align-items:center;">
                    🚀 Optimization Summary
                  </div>
                  <div style="font-size:13px; color:var(--text-muted); display:flex; flex-direction:column; gap:10px;">
                    <div style="display:flex; align-items:center; gap:8px;"><span style="color:var(--color-green-text); font-weight:900;">✔</span> <span>CO₂ reduced by: <strong style="color:var(--text-main); font-size:14px;">{co2_red}%</strong></span></div>
                    <div style="display:flex; align-items:center; gap:8px;"><span style="color:var(--color-green-text); font-weight:900;">✔</span> <span>Runtime improved by: <strong style="color:var(--text-main); font-size:14px;">{run_imp}%</strong></span></div>
                    <div style="display:flex; align-items:center; gap:8px;"><span style="color:var(--color-green-text); font-weight:900;">✔</span> <span>Energy saved: <strong style="color:var(--text-main); font-size:14px;">{enr_sav}%</strong></span></div>
                  </div>
                </div>
                <div class='eco-actions' style='justify-content:flex-end;'>
                  <button class='eco-btn-outline' onclick="window._ecoUI.toggle('{card_id}')">Close</button>
                </div>
                """
            else:
                tip_html = f"""
                <div class='eco-actions' style='justify-content:flex-end;'>
                  <button class='eco-btn-outline' onclick="window._ecoUI.toggle('{card_id}')">Close</button>
                </div>
                """

        # Info Sheet (Visual Resource Graph)
        
        # Calculate spiky polyline coordinates (Height = 60, Width = 200)
        # 100% -> y=2, 0% -> y=58
        import random
        def _gen_path(val):
            pts = []
            for i in range(11):
                x = i * 20
                jitter = random.uniform(-4, 4) if val > 5 else 0
                y = 58 - (val / 100.0) * 56 + jitter
                y = max(2, min(58, y))
                pts.append(f"{x},{y:.1f}")
            return " ".join(pts)

        cpu_path = _gen_path(cpu)
        gpu_path = _gen_path(gpu)
        
        svg_graph = f"""
        <div class='eco-graph-container'>
          <svg class='eco-graph-svg' viewBox="0 0 200 60" preserveAspectRatio="none">
            <line x1="0" y1="15" x2="200" y2="15" class='eco-graph-axis' stroke-dasharray="2,2"/>
            <line x1="0" y1="30" x2="200" y2="30" class='eco-graph-axis' stroke-dasharray="2,2"/>
            <line x1="0" y1="45" x2="200" y2="45" class='eco-graph-axis' stroke-dasharray="2,2"/>
            
            <!-- CPU Polyline (Red) -->
            <polyline points="{cpu_path}" fill="none" stroke="var(--color-red)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            
            <!-- GPU Polyline (Green) -->
            <polyline points="{gpu_path}" fill="none" stroke="var(--color-green-text)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
          <div style="display:flex; justify-content:space-between; margin-top:8px;">
            <span class="eco-graph-label">0s</span>
            <span class="eco-graph-label">{_fmt(runtime * 0.33, 1)}s</span>
            <span class="eco-graph-label">{_fmt(runtime * 0.66, 1)}s</span>
            <span class="eco-graph-label">{_fmt(runtime, 1)}s</span>
          </div>
        </div>
        """

        info_modal = f"""
        <div class='eco-info-sheet' id='{info_id}'>
          <div class='eco-card-header' style='margin-bottom:20px;'>
            <span style='font-size:15px; font-weight:600; color:var(--text-highlight)'>Detailed Emission Metrics</span>
            <button class='eco-btn-outline' style='padding:4px 8px; font-size:15px; line-height:1; border:none;' onclick="window._ecoUI.closeSheet('{info_id}')">✕</button>
          </div>
          
          <div class='eco-list' style='margin-bottom:12px; padding-bottom:12px; border-bottom:1px solid var(--border-subtle)'>
            <div style='display:flex; justify-content:space-between;'><span>Total Energy Usage:</span> <span style='text-align:right'><strong>{energy_kwh:.6f} kWh</strong><br/><span style='color:var(--text-muted); font-size:11px;'>(~{_human_energy(energy_kwh)})</span></span></div>
          </div>
          
          <div style='display:flex; justify-content:space-between; font-size:12px; margin-bottom:4px;'>
              <span style='color:var(--text-muted)'>CPU Utilization:</span>
              <strong style='color:var(--color-red)'>{_fmt(cpu, 1)}%</strong>
          </div>
          <div style='display:flex; justify-content:space-between; font-size:12px; margin-bottom:4px;'>
              <span style='color:var(--text-muted)'>GPU Utilization:</span>
              <strong style='color:var(--color-green-text)'>{_fmt(gpu, 1)}%</strong>
          </div>
          
          {svg_graph}

          <div style='text-align:right;'>
            <button class='eco-btn-outline' onclick="window._ecoUI.closeSheet('{info_id}')">Done</button>
          </div>
        </div>
        """

        import json
        import html
        escaped_after = html.escape(json.dumps(str(eco_fix_after).strip()), quote=True)

        fix_modal_html = ""
        if eco_fix_before and eco_fix_after:
            fix_modal_html = f"""
            <div class='eco-info-sheet' id='{fix_id}'>
              <div class='eco-card-header' style='margin-bottom:16px;'>
                <span style='font-size:15px; font-weight:600; color:var(--text-highlight)'>⚡ Apply Eco Fix</span>
                <button class='eco-btn-outline' style='border:none; padding:4px;' onclick="window._ecoUI.closeSheet('{fix_id}')">✕</button>
              </div>
              <div style='margin-bottom:12px; font-size:13px; color:var(--text-muted);'>
                EcoML suggests the following optimization to improve energy efficiency:
              </div>
              <div style='background:rgba(0,0,0,0.3); border:1px solid var(--border-subtle); border-radius:6px; font-family:monospace; font-size:12px; overflow-x:auto; margin-bottom:16px;'>
                <div style='padding:8px 12px; color:#fca5a5; background:rgba(248,113,113,0.1); border-left:3px solid #f87171; white-space:pre-wrap;'>- {str(eco_fix_before).strip()}</div>
                <div style='padding:8px 12px; color:#86efac; background:rgba(74,222,128,0.1); border-left:3px solid #4ade80; white-space:pre-wrap;'>+ {str(eco_fix_after).strip()}</div>
              </div>
              <div style='font-size:12px; color:var(--text-muted); font-style:italic;'>
                Click 'Copy Code' and seamlessly paste the improvement over your original code.
              </div>
              <div style='text-align:right; margin-top:16px; display:flex; justify-content:flex-end; gap:8px;'>
                 <button class='eco-btn-filled' style='background:rgba(16,185,129,0.15); color:var(--color-green-text); font-weight:600; border:1px solid rgba(16,185,129,0.3);' onclick="navigator.clipboard.writeText({escaped_after}); this.innerText='✅ Copied!'; setTimeout(()=>this.innerText='📋 Copy Code', 2000);">📋 Copy Code</button>
                 <button class='eco-btn-outline' onclick="window._ecoUI.closeSheet('{fix_id}')">Done</button>
              </div>
            </div>
            """

        # Build Main View
        html = f"""
{STYLE}
<div class='eco-slate'>

  <div class='eco-slate-pill' onclick="window._ecoUI.toggle('{card_id}')">
    <span>🌱 {_fmt(co2, 3)}g CO₂</span>
    <span class='eco-shield-badge {badge_cls}'>🛡️ {score}</span>
  </div>

  <div class='eco-card-container'>
    
    <div class='eco-slate-card' id='{card_id}' style='{ "display: block;" if show_tip else "display: none;" }'>
      
      <div class='eco-card-header'>
        <span class='eco-card-title'>🌱 {title}</span>
        <button class='eco-info-btn' onclick="window._ecoUI.openSheet('{info_id}')" title="Technical Details">ℹ️</button>
      </div>
      
      <div class='eco-main-metric'>
        {_fmt(co2, 3)}g CO₂ <span class='eco-shield-badge {badge_cls}'>🛡️ {score}</span>
      </div>

      <div class='eco-list'>
        <div class='eco-list-item'><i class='eco-icon'>⏱️</i> Runtime: <strong>{_fmt(runtime, 1)}s</strong></div>
        <div class='eco-list-item'><i class='eco-icon'>🌡️</i> <span>System Temp: <strong>CPU {_fmt(cpu_temp, 0)}°C / GPU {_fmt(gpu_temp, 0)}°C</strong></span></div>
        <div class='eco-list-item'><i class='eco-icon'>🧠</i> <span>CPU: {cpu_txt}</span></div>
        <div class='eco-list-item'><i class='eco-icon'>🎮</i> <span>GPU: {gpu_txt}</span></div>
      </div>

      {tip_html}

    </div>

    {info_modal}
    {fix_modal_html}

  </div>
</div>
"""
        display(HTML(html))
