#!/usr/bin/env python3
"""
HSEQ Intelligence Hub V2.0 — AI Consultant Takes, Actieworkflow, Alerts
Kas Backend Architecture — EA_02

Functies:
- generate_consultant_take(): AI-powered HSEQ analyse via OpenRouter
- intelligence_v2 tables: consultant_take_json, intelligence_actions, hseq_alerts
- Dismiss/Action workflow endpoints
- Dashboard alert integratie
"""

import json
import sqlite3
import os
import time
from datetime import datetime, timedelta
from flask import request, jsonify

# ── Config ────────────────────────────────────────────────────────────────
OPENROUTER_URL = os.environ.get('OPENROUTER_URL', 'https://openrouter.ai/api/v1/chat/completions')
OPENROUTER_KEY = os.environ.get('OPENROUTER_API_KEY', '')
OPENROUTER_MODEL_CONSULTANT = 'google/gemini-2.0-flash-001'
MAX_CONSULTANT_CALLS_PER_BATCH = 10
CONSULTANT_RATE_LIMIT_DELAY = 1.0  # seconds between calls


def init_intelligence_v2_tables(db_path):
    """Create V2 tables if not exist, add consultant_take_json column to scraped_items."""
    conn = sqlite3.connect(db_path)
    c = conn.cursor()

    # Add consultant_take_json to scraped_items
    try:
        c.execute("ALTER TABLE scraped_items ADD COLUMN consultant_take_json TEXT DEFAULT NULL")
    except:
        pass

    # Add dismissed column
    try:
        c.execute("ALTER TABLE scraped_items ADD COLUMN dismissed INTEGER DEFAULT 0")
    except:
        pass

    # Add risk_level column
    try:
        c.execute("ALTER TABLE scraped_items ADD COLUMN risk_level TEXT DEFAULT 'LAAG'")
    except:
        pass

    # Intelligence actions table
    c.execute("""CREATE TABLE IF NOT EXISTS intelligence_actions (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        scraped_item_id INTEGER,
        action_type TEXT NOT NULL,
        action_data TEXT DEFAULT '{}',
        status TEXT DEFAULT 'open',
        created_at TEXT DEFAULT CURRENT_TIMESTAMP,
        closed_at TEXT DEFAULT NULL,
        title TEXT DEFAULT '',
        source TEXT DEFAULT '',
        url TEXT DEFAULT ''
    )""")

    # HSEQ Alerts table
    c.execute("""CREATE TABLE IF NOT EXISTS hseq_alerts (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        title TEXT NOT NULL,
        message TEXT DEFAULT '',
        priority TEXT DEFAULT 'LAAG',
        source TEXT DEFAULT '',
        source_url TEXT DEFAULT '',
        is_read INTEGER DEFAULT 0,
        created_at TEXT DEFAULT CURRENT_TIMESTAMP,
        scraped_item_id INTEGER DEFAULT NULL
    )""")

    conn.commit()
    conn.close()


def generate_consultant_take(title, summary, source, category):
    """Generate AI consultant take using OpenRouter. Returns dict or None on failure."""
    import urllib.request
    import urllib.error

    if not OPENROUTER_KEY:
        return None

    prompt = f"""Je bent een senior HSEQ consultant (Health, Safety, Environment & Quality) werkzaam in de Nederlandse olie-, gas- en petrochemische industrie.

Analyseer het volgende HSEQ-nieuwsbericht en geef een praktisch advies:

**Titel:** {title[:200]}
**Bron:** {source}
**Samenvatting:** {summary[:500]}
**Categorie:** {category}

Reageer ALLEEN in het volgende JSON-formaat (geen markdown, geen uitleg):
{{"risk_level": "LAAG|MEDIUM|HOOG|KRITIEK", "consultant_take": "2-3 zinnen praktisch advies", "actions": ["actie 1", "actie 2", "actie 3"]}}

Kies de risk_level op basis van:
- KRITIEK: direct levensgevaar, boetes > €1M, onmiddellijke stillegging
- HOOG: ernstig letsel risico, significante wetswijziging, milieuschade
- MEDIUM: wijziging in regelgeving, best practices, industry alerts
- LAAG: informatief, algemeen nieuws, lage impact"""

    try:
        payload = json.dumps({
            "model": OPENROUTER_MODEL_CONSULTANT,
            "messages": [{"role": "user", "content": prompt}],
            "temperature": 0.3,
            "max_tokens": 500
        }).encode('utf-8')

        req = urllib.request.Request(OPENROUTER_URL, data=payload, headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {OPENROUTER_KEY}",
            "HTTP-Referer": "https://mescalinerabbit.shop",
            "X-Title": "HSEQ Intelligence Hub V2"
        })

        resp = urllib.request.urlopen(req, timeout=30)
        data = json.loads(resp.read().decode('utf-8'))
        content = data['choices'][0]['message']['content'].strip()

        # Strip markdown code blocks if present
        if content.startswith('```'):
            content = content.split('\n', 1)[1] if '\n' in content else content[3:]
            content = content.rsplit('```', 1)[0] if '```' in content else content

        result = json.loads(content)
        # Validate risk_level
        rl = result.get('risk_level', 'LAAG').upper()
        if rl not in ('LAAG', 'MEDIUM', 'HOOG', 'KRITIEK'):
            rl = 'LAAG'
        result['risk_level'] = rl
        return result

    except Exception as e:
        print(f'[Intelligence V2] AI call failed: {e}')
        return None


def generate_fallback_take(title, summary, source):
    """Rule-based fallback when AI is unavailable."""
    text = (title + ' ' + summary).lower()

    if any(k in text for k in ['waarschuwing', 'alert', 'nood', 'ongeval', 'boete', 'dodelijk', 'explosie', 'brand', 'lekgift', 'blootstelling']):
        return {"risk_level": "HOOG", "consultant_take": "Dit item vereist directe aandacht. Neem contact op met de HSEQ manager voor evaluatie van de impact op de organisatie.", "actions": ["Evalueer impact op bedrijfsvoering", "Informeer betrokken afdelingen", "Update RI&E indien relevant"]}
    elif any(k in text for k in ['nieuwe regel', 'wet', 'verplicht', 'wijziging', 'besluit', 'richtlijn', 'wetgeving']):
        return {"risk_level": "MEDIUM", "consultant_take": "Wets- of regelwijziging gedetecteerd. Controleer of deze van toepassing is op de huidige activiteiten en vergunningen.", "actions": ["Controleer toepasselijkheid", "Evalueer compliance gap", "Plan implementatie"]}
    else:
        return {"risk_level": "LAAG", "consultant_take": "Informatief item. Bewaar voor referentie en monitor op verdere ontwikkelingen.", "actions": ["Archiveer als referentie", "Monitor op updates"]}


def batch_generate_consultant_takes(db_path, limit=10):
    """Generate consultant takes for scraped items without one. Rate limited."""
    conn = sqlite3.connect(db_path)
    rows = conn.execute("""
        SELECT id, title, url, content, source_id, category
        FROM scraped_items
        WHERE consultant_take_json IS NULL AND dismissed = 0
        ORDER BY id DESC
        LIMIT ?
    """, (limit,)).fetchall()

    if not rows:
        conn.close()
        return 0

    generated = 0
    for i, row in enumerate(rows):
        item_id, title, url, content, source, category = row
        take = generate_consultant_take(
            title or '', content or '', source or '', category or ''
        )
        if take is None:
            take = generate_fallback_take(title or '', content or '', source or '')

        risk_level = take.get('risk_level', 'LAAG')
        conn.execute("""
            UPDATE scraped_items
            SET consultant_take_json = ?, risk_level = ?
            WHERE id = ?
        """, (json.dumps(take, ensure_ascii=False), risk_level, item_id))

        # Auto-create alert for HOOG/CRITICAL items
        if risk_level in ('HOOG', 'KRITIEK'):
            existing = conn.execute(
                "SELECT id FROM hseq_alerts WHERE scraped_item_id = ? AND priority = ?",
                (item_id, risk_level)
            ).fetchone()
            if not existing:
                conn.execute("""
                    INSERT INTO hseq_alerts (title, message, priority, source, source_url, scraped_item_id)
                    VALUES (?, ?, ?, ?, ?, ?)
                """, (title[:200], take.get('consultant_take', ''), risk_level, source or '', url or '', item_id))

        conn.commit()
        generated += 1

        if i < len(rows) - 1:
            time.sleep(CONSULTANT_RATE_LIMIT_DELAY)

    conn.close()
    return generated


def register_intelligence_v2_routes(app, page, BASE_PATH, DB_PATH):
    """Register all V2 API routes."""
    init_intelligence_v2_tables(DB_PATH)

    # ── Generate Consultant Takes (batch) ─────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/generate', methods=['POST'])
    def api_intelligence_v2_generate():
        """Generate AI consultant takes for items missing one."""
        try:
            limit = min(request.json.get('limit', 10), MAX_CONSULTANT_CALLS_PER_BATCH) if request.is_json else MAX_CONSULTANT_CALLS_PER_BATCH
            count = batch_generate_consultant_takes(DB_PATH, limit=limit)
            return jsonify({'status': 'ok', 'generated': count})
        except Exception as e:
            return jsonify({'status': 'error', 'error': str(e)}), 500

    # ── Get items with consultant takes ──────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/items')
    def api_intelligence_v2_items():
        """Get scraped items with consultant takes, ordered by risk level."""
        risk_filter = request.args.get('filter', '')
        try:
            conn = sqlite3.connect(DB_PATH)
            count_check = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE dismissed = 0 AND risk_level IN ('HOOG', 'KRITIEK')").fetchone()[0]
            print(f"[DEBUG] High-risk count in DB: {count_check}")
            if risk_filter == 'high-risk':
                rows = conn.execute("""
                    SELECT id, source_id, title, url, content, scraped_at, category,
                           consultant_take_json, risk_level, dismissed
                    FROM scraped_items
                    WHERE dismissed = 0 AND risk_level IN ('HOOG', 'KRITIEK')
                    ORDER BY id DESC LIMIT 50
                """).fetchall()
            else:
                rows = conn.execute("""
                    SELECT id, source_id, title, url, content, scraped_at, category,
                           consultant_take_json, risk_level, dismissed
                    FROM scraped_items
                    WHERE dismissed = 0 AND consultant_take_json IS NOT NULL
                    ORDER BY CASE risk_level WHEN 'KRITIEK' THEN 1 WHEN 'HOOG' THEN 2 WHEN 'MEDIUM' THEN 3 ELSE 4 END, id DESC LIMIT 50
                """).fetchall()
            items = []
            for r in rows:
                take = {}
                if r[8]:
                    try:
                        take = json.loads(r[8])
                    except:
                        take = {}
                items.append({
                    'id': r[0],
                    'source': (r[1] or '').replace('_', ' ').title(),
                    'title': r[2][:200],
                    'url': r[3],
                    'summary': (r[4] or '')[:300],
                    'date': (r[5] or '')[:10],
                    'category': r[6] or '',
                    'consultant_take': take.get('consultant_take', ''),
                    'risk_level': r[9] or 'LAAG',
                    'actions': take.get('actions', []),
                })
            conn.close()
            return jsonify({'items': items, 'count': len(items)})
        except Exception as e:
            return jsonify({'items': [], 'count': 0, 'error': str(e)})

    # ── Dismiss item ─────────────────────────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/<int:item_id>/dismiss', methods=['POST'])
    def api_intelligence_v2_dismiss(item_id):
        try:
            conn = sqlite3.connect(DB_PATH)
            conn.execute("UPDATE scraped_items SET dismissed = 1 WHERE id = ?", (item_id,))
            conn.commit()
            conn.close()
            return jsonify({'status': 'dismissed', 'id': item_id})
        except Exception as e:
            return jsonify({'status': 'error', 'error': str(e)}), 500

    # ── Create action from item ──────────────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/<int:item_id>/action', methods=['POST'])
    def api_intelligence_v2_action(item_id):
        try:
            payload = request.get_json(force=True)
            action_type = payload.get('action_type', 'custom')
            action_data = payload.get('action_data', '{}')

            conn = sqlite3.connect(DB_PATH)
            item = conn.execute("SELECT title, source_id, url FROM scraped_items WHERE id = ?", (item_id,)).fetchone()

            conn.execute("""
                INSERT INTO intelligence_actions (scraped_item_id, action_type, action_data, title, source, url)
                VALUES (?, ?, ?, ?, ?, ?)
            """, (item_id, action_type, action_data,
                  item[0][:200] if item else '', (item[1] or '').replace('_', ' ').title() if item else '',
                  item[2] or '' if item else ''))
            new_id = conn.execute('SELECT last_insert_rowid()').fetchone()[0]
            conn.commit()
            conn.close()
            return jsonify({'status': 'created', 'id': new_id})
        except Exception as e:
            return jsonify({'status': 'error', 'error': str(e)}), 500

    # ── Get open actions ─────────────────────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/actions')
    def api_intelligence_v2_actions():
        try:
            conn = sqlite3.connect(DB_PATH)
            rows = conn.execute("""
                SELECT ia.id, ia.scraped_item_id, ia.action_type, ia.action_data,
                       ia.status, ia.created_at, ia.title, ia.source, ia.url
                FROM intelligence_actions ia
                WHERE ia.status = 'open'
                ORDER BY ia.created_at DESC
                LIMIT 50
            """).fetchall()
            actions = []
            for r in rows:
                actions.append({
                    'id': r[0], 'scraped_item_id': r[1], 'action_type': r[2],
                    'action_data': r[3], 'status': r[4], 'created_at': r[5],
                    'title': r[6], 'source': r[7], 'url': r[8]
                })
            conn.close()
            return jsonify({'actions': actions, 'count': len(actions)})
        except Exception as e:
            return jsonify({'actions': [], 'count': 0, 'error': str(e)})

    # ── Close action ─────────────────────────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/actions/<int:action_id>/close', methods=['POST'])
    def api_intelligence_v2_close_action(action_id):
        try:
            conn = sqlite3.connect(DB_PATH)
            conn.execute("UPDATE intelligence_actions SET status = 'closed', closed_at = ? WHERE id = ?",
                         (datetime.now().isoformat(), action_id))
            conn.commit()
            conn.close()
            return jsonify({'status': 'closed', 'id': action_id})
        except Exception as e:
            return jsonify({'status': 'error', 'error': str(e)}), 500

    # ── Alerts ───────────────────────────────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/alerts')
    def api_intelligence_v2_alerts():
        """Get unread alerts (HOOG/CRITICAL priority)."""
        try:
            conn = sqlite3.connect(DB_PATH)
            rows = conn.execute("""
                SELECT id, title, message, priority, source, source_url, is_read, created_at, scraped_item_id
                FROM hseq_alerts
                WHERE is_read = 0 AND priority IN ('HOOG', 'KRITIEK')
                ORDER BY
                    CASE priority WHEN 'KRITIEK' THEN 1 WHEN 'HOOG' THEN 2 END,
                    created_at DESC
                LIMIT 20
            """).fetchall()
            alerts = []
            for r in rows:
                alerts.append({
                    'id': r[0], 'title': r[1], 'message': r[2], 'priority': r[3],
                    'source': r[4], 'url': r[5], 'is_read': r[6], 'created_at': r[7],
                    'scraped_item_id': r[8]
                })
            conn.close()
            return jsonify({'alerts': alerts, 'count': len(alerts)})
        except Exception as e:
            return jsonify({'alerts': [], 'count': 0, 'error': str(e)})

    @app.route(BASE_PATH + '/api/intelligence/v2/alerts/count')
    def api_intelligence_v2_alerts_count():
        try:
            conn = sqlite3.connect(DB_PATH)
            count = conn.execute(
                "SELECT COUNT(*) FROM hseq_alerts WHERE is_read = 0 AND priority IN ('HOOG', 'KRITIEK')"
            ).fetchone()[0]
            conn.close()
            return jsonify({'count': count})
        except:
            return jsonify({'count': 0})

    @app.route(BASE_PATH + '/api/intelligence/v2/alerts/<int:alert_id>/read', methods=['POST'])
    def api_intelligence_v2_alert_read(alert_id):
        try:
            conn = sqlite3.connect(DB_PATH)
            conn.execute("UPDATE hseq_alerts SET is_read = 1 WHERE id = ?", (alert_id,))
            conn.commit()
            conn.close()
            return jsonify({'status': 'read'})
        except Exception as e:
            return jsonify({'status': 'error', 'error': str(e)}), 500

    @app.route(BASE_PATH + '/api/intelligence/v2/alerts/read-all', methods=['POST'])
    def api_intelligence_v2_alerts_read_all():
        try:
            conn = sqlite3.connect(DB_PATH)
            conn.execute("UPDATE hseq_alerts SET is_read = 1")
            conn.commit()
            conn.close()
            return jsonify({'status': 'all_read'})
        except Exception as e:
            return jsonify({'status': 'error', 'error': str(e)}), 500

    # ── Dashboard alert summary (for main page) ──────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/dashboard-summary')
    def api_intelligence_v2_dashboard():
        """Summary data for main dashboard integration."""
        try:
            conn = sqlite3.connect(DB_PATH)
            open_alerts = conn.execute(
                "SELECT COUNT(*) FROM hseq_alerts WHERE is_read = 0 AND priority IN ('HOOG', 'KRITIEK')"
            ).fetchone()[0]
            total_items = conn.execute(
                "SELECT COUNT(*) FROM scraped_items WHERE consultant_take_json IS NOT NULL AND dismissed = 0"
            ).fetchone()[0]
            last_alert = conn.execute(
                "SELECT created_at FROM hseq_alerts ORDER BY created_at DESC LIMIT 1"
            ).fetchone()
            # Get top 5 high-risk items for dashboard widget
            rows = conn.execute("""
                SELECT id, title, risk_level, source_id, scraped_at
                FROM scraped_items
                WHERE risk_level IN ('HOOG', 'KRITIEK') AND dismissed = 0
                ORDER BY CASE risk_level WHEN 'KRITIEK' THEN 1 WHEN 'HOOG' THEN 2 END, id DESC
                LIMIT 5
            """).fetchall()
            top_risks = [{'id': r[0], 'title': r[1][:100], 'risk': r[2], 'source': (r[3] or '').replace('_', ' ').title(), 'date': (r[4] or '')[:10]} for r in rows]
            conn.close()
            return jsonify({
                'open_alerts': open_alerts,
                'total_analyzed': total_items,
                'last_alert': last_alert[0] if last_alert else None,
                'top_risks': top_risks
            })
        except Exception as e:
            return jsonify({'open_alerts': 0, 'total_analyzed': 0, 'last_alert': None, 'top_risks': [], 'error': str(e)})

    # ── Stats for intelligence page ──────────────────────────────────────
    @app.route(BASE_PATH + '/api/intelligence/v2/stats')
    def api_intelligence_v2_stats():
        try:
            conn = sqlite3.connect(DB_PATH)
            total = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE dismissed = 0").fetchone()[0]
            analyzed = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE consultant_take_json IS NOT NULL AND dismissed = 0").fetchone()[0]
            dismissed = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE dismissed = 1").fetchone()[0]
            open_actions = conn.execute("SELECT COUNT(*) FROM intelligence_actions WHERE status = 'open'").fetchone()[0]
            risks = {}
            for level in ('KRITIEK', 'HOOG', 'MEDIUM', 'LAAG'):
                risks[level] = conn.execute(
                    "SELECT COUNT(*) FROM scraped_items WHERE risk_level = ? AND dismissed = 0",
                    (level,)
                ).fetchone()[0]
            conn.close()
            return jsonify({
                'total': total, 'analyzed': analyzed, 'dismissed': dismissed,
                'open_actions': open_actions, 'risks': risks
            })
        except Exception as e:
            return jsonify({'total': 0, 'analyzed': 0, 'dismissed': 0, 'open_actions': 0, 'risks': {}, 'error': str(e)})


def build_intelligence_v2_html(BASE_PATH, DB_PATH):
    """Build the V2 Intelligence Hub page HTML with consultant takes, action buttons, alerts."""
    conn = sqlite3.connect(DB_PATH)
    init_intelligence_v2_tables(DB_PATH)

    # Stats
    total = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE dismissed = 0").fetchone()[0]
    analyzed = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE consultant_take_json IS NOT NULL AND dismissed = 0").fetchone()[0]
    dismissed = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE dismissed = 1").fetchone()[0]
    open_actions = conn.execute("SELECT COUNT(*) FROM intelligence_actions WHERE status = 'open'").fetchone()[0]
    open_alerts = conn.execute("SELECT COUNT(*) FROM hseq_alerts WHERE is_read = 0 AND priority IN ('HOOG','KRITIEK')").fetchone()[0]
    risks = {}
    for level in ('KRITIEK', 'HOOG', 'MEDIUM', 'LAAG'):
        risks[level] = conn.execute("SELECT COUNT(*) FROM scraped_items WHERE risk_level = ? AND dismissed = 0", (level,)).fetchone()[0]

    # Get items with consultant takes
    rows = conn.execute("""
        SELECT id, source_id, title, url, content, scraped_at, category,
               consultant_take_json, risk_level
        FROM scraped_items
        WHERE dismissed = 0 AND consultant_take_json IS NOT NULL
        ORDER BY CASE risk_level WHEN 'KRITIEK' THEN 1 WHEN 'HOOG' THEN 2 WHEN 'MEDIUM' THEN 3 ELSE 4 END, id DESC
        LIMIT 50
    """).fetchall()

    # Get open V2 actions
    v2_actions = conn.execute("""
        SELECT id, scraped_item_id, action_type, action_data, title, source, created_at
        FROM intelligence_actions WHERE status = 'open'
        ORDER BY created_at DESC LIMIT 20
    """).fetchall()

    # Get alerts
    alerts = conn.execute("""
        SELECT id, title, message, priority, source, source_url, created_at
        FROM hseq_alerts WHERE is_read = 0
        ORDER BY CASE priority WHEN 'KRITIEK' THEN 1 WHEN 'HOOG' THEN 2 WHEN 'MEDIUM' THEN 3 ELSE 4 END, created_at DESC
        LIMIT 10
    """).fetchall()

    # Get pending items (no consultant take yet)
    pending = conn.execute("""
        SELECT COUNT(*) FROM scraped_items WHERE consultant_take_json IS NULL AND dismissed = 0
    """).fetchone()[0]

    conn.close()

    risk_colors = {'KRITIEK': '#DC2626', 'HOOG': '#EF4444', 'MEDIUM': '#F59E0B', 'LAAG': '#00A859'}
    risk_labels = {'KRITIEK': '🔴 Kritiek', 'HOOG': '🟠 Hoog', 'MEDIUM': '🟡 Medium', 'LAAG': '🟢 Laag'}

    body = '''
    <style>
      .v2-grid{display:grid;grid-template-columns:300px 1fr;gap:20px}
      .v2-sidebar{display:flex;flex-direction:column;gap:12px}
      .v2-main{display:flex;flex-direction:column;gap:16px}
      .v2-card{background:#fff;border-radius:8px;padding:16px;box-shadow:0 1px 3px rgba(0,0,0,.08)}
      .v2-card h4{margin:0 0 10px;font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:#868E96;font-weight:600}
      .risk-bar{display:flex;gap:6px;align-items:center;margin-bottom:8px}
      .risk-segment{height:8px;border-radius:4px;transition:all .3s}
      .stat-row{display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid #F1F3F5;font-size:13px}
      .stat-row:last-child{border:none}
      .stat-row .val{font-weight:600;color:#1a202c}
      .stat-row .lbl{color:#868E96}
      .v2-tabs{display:flex;gap:0;border-bottom:2px solid #E9ECEF;margin-bottom:16px}
      .v2-tab{padding:10px 18px;font-size:13px;font-weight:500;color:#868E96;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;transition:all .2s}
      .v2-tab:hover{color:#003366}
      .v2-tab.active{color:#003366;border-bottom-color:#003366;font-weight:600}
      .v2-tab .badge-count{background:#EF4444;color:#fff;font-size:9px;font-weight:700;border-radius:50%;padding:1px 5px;margin-left:6px}
      .v2-tab-content{display:none}
      .v2-tab-content.active{display:block}
      .insight-v2{background:#fff;border-radius:8px;padding:14px;margin-bottom:10px;border:1px solid #E9ECEF;border-left:4px solid #E9ECEF;transition:all .2s}
      .insight-v2:hover{box-shadow:0 2px 8px rgba(0,0,0,.06)}
      .insight-v2.risk-KRITIEK{border-left-color:#DC2626;background:#FEF2F2}
      .insight-v2.risk-HOOG{border-left-color:#EF4444;background:#FFF5F5}
      .insight-v2.risk-MEDIUM{border-left-color:#F59E0B;background:#FFFBEB}
      .insight-v2.risk-LAAG{border-left-color:#00A859;background:#F0FFF4}
      .insight-v2 .title{font-weight:600;font-size:13px;color:#1a202c;margin-bottom:4px}
      .insight-v2 .meta{font-size:11px;color:#868E96;margin-bottom:6px}
      .insight-v2 .take{font-size:12px;color:#495057;line-height:1.6;padding:8px 10px;background:rgba(255,255,255,.7);border-radius:4px;border:1px solid #E9ECEF;margin:6px 0}
      .risk-badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600;color:#fff}
      .action-btns{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap}
      .btn-sm{padding:5px 12px;border-radius:6px;font-size:11px;font-weight:500;cursor:pointer;border:none;transition:all .2s;text-decoration:none;display:inline-flex;align-items:center;gap:4px}
      .btn-primary{background:#003366;color:#fff}.btn-primary:hover{background:#001a33}
      .btn-danger{background:#EF4444;color:#fff}.btn-danger:hover{background:#DC2626}
      .btn-outline{background:#fff;color:#003366;border:1px solid #DEE2E6}.btn-outline:hover{background:#F8F9FA}
      .btn-success{background:#00A859;color:#fff}.btn-success:hover{background:#009950}
      .btn-warn{background:#F59E0B;color:#fff}.btn-warn:hover{background:#D97706}
      .action-dropdown{position:relative;display:inline-block}
      .action-dropdown-menu{display:none;position:absolute;top:100%;left:0;background:#fff;border:1px solid #DEE2E6;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.12);z-index:100;min-width:220px;padding:4px 0;margin-top:4px}
      .action-dropdown-menu.show{display:block}
      .action-dropdown-item{padding:8px 14px;font-size:12px;cursor:pointer;display:flex;align-items:center;gap:8px;transition:background .15s}
      .action-dropdown-item:hover{background:#F8F9FA}
      .action-v2{display:flex;align-items:start;gap:10px;padding:10px 12px;background:#fff;border-radius:8px;margin-bottom:6px;border:1px solid #E9ECEF}
      .action-v2 .a-type{font-size:10px;font-weight:600;padding:2px 8px;border-radius:4px;color:#fff;white-space:nowrap}
      .action-v2 .a-body{flex:1;font-size:12px}
      .action-v2 .a-body .a-title{font-weight:600;color:#1a202c}
      .action-v2 .a-body .a-meta{color:#868E96;font-size:11px}
      .alert-item{padding:10px 12px;background:#fff;border-radius:8px;margin-bottom:6px;border-left:4px solid #EF4444;transition:all .2s}
      .alert-item:hover{box-shadow:0 2px 6px rgba(0,0,0,.06)}
      .alert-item .a-title{font-weight:600;font-size:12px;color:#1a202c}
      .alert-item .a-msg{font-size:11px;color:#495057;margin-top:3px}
      .alert-item .a-meta{font-size:10px;color:#868E96;margin-top:4px}
      .generate-banner{text-align:center;padding:16px;background:linear-gradient(135deg,#EBF4FF,#E6FFFA);border-radius:8px;border:1px solid #BEE3F8;margin-bottom:16px}
      .generate-banner .pending-count{font-size:24px;font-weight:700;color:#003366}
      .generate-banner .pending-label{font-size:12px;color:#4A5568}
      .empty-state{text-align:center;padding:40px;color:#868E96}
      .empty-state .icon{font-size:32px;margin-bottom:8px}
    </style>

    <div class="v2-grid">
      <!-- SIDEBAR -->
      <div class="v2-sidebar">
        <!-- Generate Banner -->
        <div class="generate-banner">
          <div class="pending-count">''' + str(pending) + '''</div>
          <div class="pending-label">items wachten op AI analyse</div>
          <button class="btn-sm btn-primary" style="margin-top:10px;padding:8px 20px;font-size:12px" onclick="generateTakes()">
            🧠 Genereer Consultant Takes
          </button>
        </div>

        <!-- Risico Verdeling -->
        <div class="v2-card">
          <h4>Risico Verdeling</h4>
          <div class="risk-bar">'''

    total_risk = max(sum(risks.values()), 1)
    for level, color in risk_colors.items():
        pct = round((risks.get(level, 0) / total_risk) * 100)
        if risks.get(level, 0) > 0:
            body += f'<div class="risk-segment" style="width:{pct}%;background:{color}" title="{risk_labels[level]}: {risks[level]}"></div>'

    body += '''</div>
          <div class="stat-row"><span class="lbl">🔴 Kritiek</span><span class="val" style="color:#DC2626">''' + str(risks.get('KRITIEK', 0)) + '''</span></div>
          <div class="stat-row"><span class="lbl">🟠 Hoog</span><span class="val" style="color:#EF4444">''' + str(risks.get('HOOG', 0)) + '''</span></div>
          <div class="stat-row"><span class="lbl">🟡 Medium</span><span class="val" style="color:#F59E0B">''' + str(risks.get('MEDIUM', 0)) + '''</span></div>
          <div class="stat-row"><span class="lbl">🟢 Laag</span><span class="val" style="color:#00A859">''' + str(risks.get('LAAG', 0)) + '''</span></div>
        </div>

        <!-- Stats -->
        <div class="v2-card">
          <h4>Statistieken</h4>
          <div class="stat-row"><span class="lbl">📊 Totaal items</span><span class="val">''' + str(total) + '''</span></div>
          <div class="stat-row"><span class="lbl">🧠 Geanalyseerd</span><span class="val">''' + str(analyzed) + '''</span></div>
          <div class="stat-row"><span class="lbl">✅ Afgehandeld</span><span class="val">''' + str(dismissed) + '''</span></div>
          <div class="stat-row"><span class="lbl">📋 Open acties</span><span class="val" style="color:#003366">''' + str(open_actions) + '''</span></div>
          <div class="stat-row"><span class="lbl">🚨 Unread alerts</span><span class="val" style="color:#EF4444">''' + str(open_alerts) + '''</span></div>
        </div>

        <!-- Quick Actions -->
        <div class="v2-card">
          <h4>Snelle Acties</h4>
          <div style="display:flex;flex-direction:column;gap:6px">
            <a href="{{BASE_PATH}}/lms/" class="btn-sm btn-outline" style="text-align:center">🎓 LMS Academy</a>
            <a href="{{BASE_PATH}}/rie" class="btn-sm btn-outline" style="text-align:center">📋 RI&E / HAZOP</a>
            <a href="{{BASE_PATH}}/agents" class="btn-sm btn-outline" style="text-align:center">🤖 Agent Launchpad</a>
            <a href="{{BASE_PATH}}/incidents-env" class="btn-sm btn-outline" style="text-align:center">🚨 Incidenten</a>
          </div>
        </div>
      </div>

      <!-- MAIN -->
      <div class="v2-main">
        <!-- Tabs -->
        <div class="v2-tabs">
          <div class="v2-tab active" onclick="switchV2Tab('feed')">🧠 Intelligence Feed</div>
          <div class="v2-tab" onclick="switchV2Tab('actions')">📋 Acties <span class="badge-count">''' + str(open_actions) + '''</span></div>
          <div class="v2-tab" onclick="switchV2Tab('alerts')">🚨 Alerts <span class="badge-count" style="background:#EF4444">''' + str(open_alerts) + '''</span></div>
        </div>

        <!-- TAB: Intelligence Feed -->
        <div class="v2-tab-content active" id="v2tab-feed">'''

    if rows:
        for r in rows:
            item_id, source, title, url, content, scraped_at, category, take_json, risk_level = r
            take = {}
            if take_json:
                try: take = json.loads(take_json)
                except: pass

            risk_cls = risk_level or 'LAAG'
            rc = risk_colors.get(risk_cls, '#868E96')
            take_text = take.get('consultant_take', '')
            actions_list = take.get('actions', [])
            src_name = (source or '').replace('_', ' ').title()

            body += f'''
          <div class="insight-v2 risk-{risk_cls}" id="item-{item_id}">
            <div style="display:flex;justify-content:space-between;align-items:start;gap:8px">
              <div class="title">{title[:200]}</div>
              <span class="risk-badge" style="background:{rc}">{risk_labels.get(risk_cls, risk_cls)}</span>
            </div>
            <div class="meta">{src_name} · {category or 'Algemeen'} · {(scraped_at or '')[:10]}</div>
            <div style="font-size:12px;color:#495057;line-height:1.5;margin:6px 0">{(content or '')[:250]}</div>'''

            if take_text:
                body += f'''
            <div class="take">💡 <strong>Consultant Take:</strong> {take_text}</div>'''

            if actions_list:
                body += '<div style="margin:6px 0;font-size:11px;color:#868E96"><strong>Voorgestelde acties:</strong><ul style="margin:4px 0 0;padding-left:18px">'
                for a in actions_list[:3]:
                    body += f'<li>{a}</li>'
                body += '</ul></div>'

            body += f'''
            <div class="action-btns">
              <div class="action-dropdown">
                <button class="btn-sm btn-primary" onclick="toggleDropdown(this)">✅ Actie ondernemen</button>
                <div class="action-dropdown-menu">
                  <div class="action-dropdown-item" onclick="createV2Action({item_id},'training','🎓 Start Training')">🎓 Maak Training (LMS)</div>
                  <div class="action-dropdown-item" onclick="createV2Action({item_id},'news','📰 Nieuwsbericht')">📰 Genereer Nieuwsbericht</div>
                  <div class="action-dropdown-item" onclick="createV2Action({item_id},'rie','📋 RI&E Update')">📋 Update RI&E</div>
                  <div class="action-dropdown-item" onclick="createV2Action({item_id},'alert','📢 Team Alert')">📢 Stuur Team Alert</div>
                  <div class="action-dropdown-item" onclick="createV2Action({item_id},'custom','📝 Eigen Actie')">📝 Eigen Actie</div>
                </div>
              </div>
              <button class="btn-sm btn-outline" onclick="dismissItem({item_id})">❌ Afwijzen</button>
              {f'<a href="{url}" target="_blank" class="btn-sm btn-outline">🔗 Bron</a>' if url else ''}
            </div>
          </div>'''
    else:
        body += '<div class="empty-state"><div class="icon">🧠</div><div>Geen geanalyseerde items. Klik op "Genereer Consultant Takes" om te starten.</div></div>'

    body += '''
        </div>

        <!-- TAB: Acties -->
        <div class="v2-tab-content" id="v2tab-actions">'''

    if v2_actions:
        action_type_labels = {'training': '🎓 Training', 'news': '📰 Nieuws', 'rie': '📋 RI&E', 'alert': '📢 Alert', 'custom': '📝 Actie'}
        action_type_colors = {'training': '#003366', 'news': '#7950F2', 'rie': '#00A859', 'alert': '#EF4444', 'custom': '#F59E0B'}
        for a in v2_actions:
            aid, sitem_id, atype, adata, atitle, asource, acreated = a
            atc = action_type_colors.get(atype, '#868E96')
            atl = action_type_labels.get(atype, atype)
            body += f'''
          <div class="action-v2" id="v2action-{aid}">
            <span class="a-type" style="background:{atc}">{atl}</span>
            <div class="a-body">
              <div class="a-title">{(atitle or 'Onbekend')[:100]}</div>
              <div class="a-meta">{asource} · {acreated[:16] if acreated else ''}</div>
            </div>
            <button class="btn-sm btn-success" onclick="closeV2Action({aid}, this)">✓ Afhandelen</button>
          </div>'''
    else:
        body += '<div class="empty-state"><div class="icon">📋</div><div>Geen openstaande acties</div></div>'

    body += '''
        </div>

        <!-- TAB: Alerts -->
        <div class="v2-tab-content" id="v2tab-alerts">'''

    if alerts:
        for al in alerts:
            alid, altitle, almsg, alpri, alsrc, alurl, alcreated = al
            alc = '#DC2626' if alpri == 'KRITIEK' else '#EF4444'
            body += f'''
          <div class="alert-item" style="border-left-color:{alc}" id="alert-{alid}">
            <div style="display:flex;justify-content:space-between;align-items:start">
              <div class="a-title">{(altitle or '')[:150]}</div>
              <span class="risk-badge" style="background:{alc}">{alpri}</span>
            </div>
            <div class="a-msg">{(almsg or '')[:200]}</div>
            <div class="a-meta">{alsrc} · {alcreated[:16] if alcreated else ''}</div>
            <div style="margin-top:6px;display:flex;gap:6px">
              <button class="btn-sm btn-outline" onclick="markAlertRead({alid})">✓ Gelezen</button>
              {f'<a href="{alurl}" target="_blank" class="btn-sm btn-outline">🔗 Bron</a>' if alurl else ''}
            </div>
          </div>'''
        body += '<div style="text-align:center;margin-top:12px"><button class="btn-sm btn-outline" onclick="markAllAlertsRead()">✅ Markeer alles als gelezen</button></div>'
    else:
        body += '<div class="empty-state"><div class="icon">🟢</div><div>Geen openstaande alerts</div></div>'

    body += '''
        </div>
      </div>
    </div>

    <script>
    function switchV2Tab(tab) {
        document.querySelectorAll('.v2-tab-content').forEach(t => t.classList.remove('active'));
        document.querySelectorAll('.v2-tab').forEach(t => t.classList.remove('active'));
        document.getElementById('v2tab-' + tab).classList.add('active');
        event.currentTarget.classList.add('active');
    }

    function toggleDropdown(btn) {
        const menu = btn.nextElementSibling;
        document.querySelectorAll('.action-dropdown-menu.show').forEach(m => { if(m !== menu) m.classList.remove('show'); });
        menu.classList.toggle('show');
    }

    // Close dropdowns on outside click
    document.addEventListener('click', function(e) {
        if (!e.target.closest('.action-dropdown')) {
            document.querySelectorAll('.action-dropdown-menu.show').forEach(m => m.classList.remove('show'));
        }
    });

    function createV2Action(itemId, actionType, label) {
        if(!confirm(label + ' aanmaken voor dit item?')) return;
        fetch('{{BASE_PATH}}/api/intelligence/v2/' + itemId + '/action', {
            method:'POST',
            headers:{'Content-Type':'application/json'},
            credentials:'same-origin',
            body: JSON.stringify({action_type: actionType, action_data: label})
        }).then(r => r.json()).then(d => {
            if(d.status === 'created') {
                showToast('✅ Actie aangemaakt');
                document.querySelectorAll('.action-dropdown-menu.show').forEach(m => m.classList.remove('show'));
            } else {
                showToast('❌ Fout: ' + (d.error || ''));
            }
        }).catch(() => showToast('❌ Netwerkfout'));
    }

    function dismissItem(itemId) {
        if(!confirm('Item afwijzen? Dit verwijdert het uit de feed.')) return;
        fetch('{{BASE_PATH}}/api/intelligence/v2/' + itemId + '/dismiss', {
            method:'POST', credentials:'same-origin'
        }).then(r => r.json()).then(d => {
            if(d.status === 'dismissed') {
                const el = document.getElementById('item-' + itemId);
                if(el) { el.style.opacity='0.3'; el.style.transition='all .3s'; setTimeout(()=>el.style.display='none', 400); }
                showToast('✅ Item afgewezen');
            }
        });
    }

    function closeV2Action(actionId, btn) {
        fetch('{{BASE_PATH}}/api/intelligence/v2/actions/' + actionId + '/close', {
            method:'POST', credentials:'same-origin'
        }).then(r => r.json()).then(d => {
            if(d.status === 'closed') {
                const el = document.getElementById('v2action-' + actionId);
                if(el) { el.style.opacity='0.3'; el.style.transition='all .3s'; setTimeout(()=>el.style.display='none', 400); }
                btn.textContent = '✓ Gesloten';
                btn.disabled = true;
                btn.style.background = '#a0aec0';
            }
        });
    }

    function markAlertRead(alertId) {
        fetch('{{BASE_PATH}}/api/intelligence/v2/alerts/' + alertId + '/read', {
            method:'POST', credentials:'same-origin'
        }).then(r => r.json()).then(d => {
            if(d.status === 'read') {
                const el = document.getElementById('alert-' + alertId);
                if(el) { el.style.opacity='0.3'; el.style.transition='all .3s'; setTimeout(()=>el.style.display='none', 400); }
            }
        });
    }

    function markAllAlertsRead() {
        fetch('{{BASE_PATH}}/api/intelligence/v2/alerts/read-all', {
            method:'POST', credentials:'same-origin'
        }).then(r => r.json()).then(d => {
            if(d.status === 'all_read') {
                document.querySelectorAll('.alert-item').forEach(el => {
                    el.style.opacity='0.3'; el.style.transition='all .3s';
                    setTimeout(()=>el.style.display='none', 400);
                });
                showToast('✅ Alle alerts gemarkeerd als gelezen');
            }
        });
    }

    function generateTakes() {
        const btn = event.target.closest('button');
        btn.textContent = '⏳ Analyseren...';
        btn.disabled = true;
        fetch('{{BASE_PATH}}/api/intelligence/v2/generate', {
            method:'POST',
            headers:{'Content-Type':'application/json'},
            credentials:'same-origin',
            body: JSON.stringify({limit: 10})
        }).then(r => r.json()).then(d => {
            if(d.status === 'ok') {
                showToast('✅ ' + d.generated + ' items geanalyseerd — pagina wordt herladen...');
                setTimeout(() => location.reload(), 1500);
            } else {
                btn.textContent = '🧠 Genereer Consultant Takes';
                btn.disabled = false;
                showToast('❌ Fout bij genereren');
            }
        }).catch(() => {
            btn.textContent = '🧠 Genereer Consultant Takes';
            btn.disabled = false;
            showToast('❌ Netwerkfout');
        });
    }

    function showToast(msg) {
        const t = document.createElement('div');
        t.textContent = msg;
        t.style.cssText = 'position:fixed;bottom:20px;right:20px;padding:10px 20px;background:#1a202c;color:#fff;border-radius:8px;font-size:13px;z-index:9999;animation:fadeIn .3s';
        document.body.appendChild(t);
        setTimeout(() => { t.style.opacity='0'; t.style.transition='opacity .3s'; setTimeout(()=>t.remove(), 300); }, 3000);
    }
    </script>'''

    return body


def build_dashboard_alert_widget(BASE_PATH):
    """Build the HSEQ Alerts widget HTML for the main dashboard page."""
    return '''
    <style>
      .dashboard-alerts{background:#fff;border-radius:8px;padding:16px;box-shadow:0 1px 3px rgba(0,0,0,.08);margin-top:16px}
      .dashboard-alerts h3{margin:0 0 12px;font-size:14px;color:#003366;display:flex;align-items:center;gap:8px}
      .dashboard-alerts h3 .alert-count{background:#EF4444;color:#fff;font-size:10px;font-weight:700;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center}
      .dash-alert-item{display:flex;align-items:start;gap:10px;padding:8px 10px;border-radius:6px;margin-bottom:4px;border-left:3px solid #E9ECEF;transition:all .15s}
      .dash-alert-item:hover{background:#F8F9FA}
      .dash-alert-item.risk-KRITIEK{border-left-color:#DC2626;background:#FEF2F2}
      .dash-alert-item.risk-HOOG{border-left-color:#EF4444;background:#FFF5F5}
      .dash-alert-item.risk-MEDIUM{border-left-color:#F59E0B;background:#FFFBEB}
      .dash-alert-item .da-title{font-size:12px;font-weight:500;color:#1a202c;flex:1}
      .dash-alert-item .da-risk{font-size:10px;font-weight:600;padding:1px 6px;border-radius:4px;color:#fff}
    </style>
    <div class="dashboard-alerts" id="dashAlertsWidget">
      <h3>🚨 HSEQ Alerts <span class="alert-count" id="dashAlertCount">-</span></h3>
      <div id="dashAlertsContent" style="font-size:12px;color:#868E96;text-align:center;padding:10px">Laden...</div>
      <div style="text-align:right;margin-top:8px">
        <a href="{{BASE_PATH}}/intelligence" style="font-size:11px;color:#003366;text-decoration:none;font-weight:500">Bekijk alle →</a>
      </div>
    </div>
    <script>
    (function(){
        fetch('{{BASE_PATH}}/api/intelligence/v2/dashboard-summary').then(r=>r.json()).then(d => {
            document.getElementById('dashAlertCount').textContent = d.open_alerts || 0;
            var html = '';
            if(d.top_risks && d.top_risks.length > 0) {
                d.top_risks.forEach(function(item) {
                    var rc = item.risk === 'KRITIEK' ? '#DC2626' : item.risk === 'HOOG' ? '#EF4444' : item.risk === 'MEDIUM' ? '#F59E0B' : '#00A859';
                    html += '<div class="dash-alert-item risk-' + item.risk + '">' +
                        '<div class="da-title">' + item.title + '</div>' +
                        '<span class="da-risk" style="background:' + rc + '">' + item.risk + '</span>' +
                        '</div>';
                });
            } else {
                html = '<div style="text-align:center;padding:10px;color:#00A859">✅ Geen hoog-risico alerts</div>';
            }
            document.getElementById('dashAlertsContent').innerHTML = html;
        }).catch(function() {
            document.getElementById('dashAlertsContent').innerHTML = '<div style="color:#868E96">Kon alerts niet laden</div>';
        });
    })();
    </script>'''
