#!/usr/bin/env python3
"""
Feed Hunter Web Portal
Self-contained dashboard for monitoring the X/Twitter feed intelligence pipeline
"""

import json
import os
import glob
from datetime import datetime, timezone
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
from urllib.parse import urlparse, parse_qs


class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    daemon_threads = True
import re

# Configuration
PORT = 8888
_PORTAL_DIR = os.path.dirname(os.path.abspath(__file__))
_PROJECT_DIR = os.path.dirname(_PORTAL_DIR)
DATA_DIR = os.path.join(_PROJECT_DIR, "data")
SKILLS_DIR = os.path.join(os.path.dirname(_PROJECT_DIR), "skills", "deep-scraper", "scripts")
X_FEED_DIR = os.path.join(os.path.dirname(_PROJECT_DIR), "..", "data", "x-feed")

class FeedHunterHandler(BaseHTTPRequestHandler):
    
    def do_GET(self):
        try:
            parsed_path = urlparse(self.path)
            path = parsed_path.path
            query = parse_qs(parsed_path.query)
            
            if path == '/' or path == '/dashboard':
                self.serve_dashboard()
            elif path == '/feed':
                self.serve_feed_view()
            elif path == '/investigations':
                self.serve_investigations()
            elif path == '/simulations':
                self.serve_simulations()
            elif path == '/status':
                self.serve_status()
            elif path == '/api/data':
                self.serve_api_data(query.get('type', [''])[0])
            elif path.startswith('/static/'):
                self.serve_static(path)
            else:
                self.send_error(404)
        except Exception as e:
            try:
                self.send_response(500)
                self.send_header('Content-type', 'text/html')
                self.end_headers()
                self.wfile.write(f"<h1>500 Error</h1><pre>{e}</pre>".encode())
            except:
                pass
    
    def serve_dashboard(self):
        """Main dashboard overview"""
        data = self.get_dashboard_data()
        html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Feed Hunter Dashboard</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <nav class="navbar">
        <div class="nav-brand">🖤 Feed Hunter</div>
        <div class="nav-links">
            <a href="/dashboard" class="active">Dashboard</a>
            <a href="/feed">Feed</a>
            <a href="/investigations">Investigations</a>
            <a href="/simulations">Simulations</a>
            <a href="/status">Status</a>
        </div>
    </nav>

    <div class="container">
        <div class="cards">
            <div class="card">
                <h3>Active Simulations</h3>
                <div class="metric-large">{data['active_simulations']}</div>
                <div class="metric-small">Total Bankroll: ${data['total_bankroll']:,.0f}</div>
            </div>
            
            <div class="card">
                <h3>Recent Scrapes</h3>
                <div class="metric-large">{data['recent_scrapes']}</div>
                <div class="metric-small">Last: {data['last_scrape']}</div>
            </div>
            
            <div class="card">
                <h3>Signals Today</h3>
                <div class="metric-large">{data['signals_today']}</div>
                <div class="metric-small">Investigated: {data['investigated_today']}</div>
            </div>
            
            <div class="card">
                <h3>P&L</h3>
                <div class="metric-large ${data['total_pnl_class']}">${data['total_pnl']:,.0f}</div>
                <div class="metric-small">{data['total_pnl_pct']:+.1f}%</div>
            </div>
        </div>

        <div class="grid">
            <div class="card">
                <h3>Recent Activity</h3>
                <div class="activity-feed">
                    {data['recent_activity']}
                </div>
            </div>
            
            <div class="card">
                <h3>Active Positions</h3>
                <div class="positions-summary">
                    {data['active_positions']}
                </div>
            </div>
        </div>
    </div>

    <script src="/static/js/dashboard.js"></script>
</body>
</html>
        """
        self.send_html(html)
    
    def serve_feed_view(self):
        """Latest scraped posts with triage status"""
        posts = self.get_latest_posts()
        html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Feed Hunter - Latest Feed</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <nav class="navbar">
        <div class="nav-brand">🖤 Feed Hunter</div>
        <div class="nav-links">
            <a href="/dashboard">Dashboard</a>
            <a href="/feed" class="active">Feed</a>
            <a href="/investigations">Investigations</a>
            <a href="/simulations">Simulations</a>
            <a href="/status">Status</a>
        </div>
    </nav>

    <div class="container">
        <h2>Latest Feed ({len(posts)} posts)</h2>
        
        <div class="feed-posts">
            {self.render_posts(posts)}
        </div>
    </div>

    <script src="/static/js/feed.js"></script>
</body>
</html>
        """
        self.send_html(html)
    
    def serve_investigations(self):
        """Investigation reports view"""
        investigations = self.get_investigations()
        html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Feed Hunter - Investigations</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <nav class="navbar">
        <div class="nav-brand">🖤 Feed Hunter</div>
        <div class="nav-links">
            <a href="/dashboard">Dashboard</a>
            <a href="/feed">Feed</a>
            <a href="/investigations" class="active">Investigations</a>
            <a href="/simulations">Simulations</a>
            <a href="/status">Status</a>
        </div>
    </nav>

    <div class="container">
        <h2>Investigation Reports</h2>
        
        <div class="investigations">
            {self.render_investigations(investigations)}
        </div>
    </div>

    <script src="/static/js/investigations.js"></script>
</body>
</html>
        """
        self.send_html(html)
    
    def serve_simulations(self):
        """Simulation tracker view"""
        sims = self.get_simulation_data()
        html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Feed Hunter - Simulations</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <nav class="navbar">
        <div class="nav-brand">🖤 Feed Hunter</div>
        <div class="nav-links">
            <a href="/dashboard">Dashboard</a>
            <a href="/feed">Feed</a>
            <a href="/investigations">Investigations</a>
            <a href="/simulations" class="active">Simulations</a>
            <a href="/status">Status</a>
        </div>
    </nav>

    <div class="container">
        <h2>Paper Trading Simulations</h2>
        
        <div class="grid">
            <div class="card">
                <h3>Active Positions</h3>
                <div class="positions">
                    {self.render_active_positions(sims.get('active', {}))}
                </div>
            </div>
            
            <div class="card">
                <h3>Performance</h3>
                <div class="performance-metrics">
                    {self.render_performance_metrics(sims)}
                </div>
            </div>
        </div>
        
        <div class="card">
            <h3>Trade History</h3>
            <div class="trade-history">
                {self.render_trade_history(sims.get('history', {}).get('closed', []) if isinstance(sims.get('history'), dict) else sims.get('history', []))}
            </div>
        </div>
    </div>

    <script src="/static/js/simulations.js"></script>
</body>
</html>
        """
        self.send_html(html)
    
    def serve_status(self):
        """Pipeline status view"""
        status = self.get_status_data()
        html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Feed Hunter - Status</title>
    <link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
    <nav class="navbar">
        <div class="nav-brand">🖤 Feed Hunter</div>
        <div class="nav-links">
            <a href="/dashboard">Dashboard</a>
            <a href="/feed">Feed</a>
            <a href="/investigations">Investigations</a>
            <a href="/simulations">Simulations</a>
            <a href="/status" class="active">Status</a>
        </div>
    </nav>

    <div class="container">
        <h2>Pipeline Status</h2>
        
        <div class="grid">
            <div class="card">
                <h3>Chrome Debug</h3>
                <div class="status-indicator ${status['chrome']['class']}">
                    {status['chrome']['status']}
                </div>
                <div class="status-detail">{status['chrome']['detail']}</div>
            </div>
            
            <div class="card">
                <h3>Last Pipeline Run</h3>
                <div class="status-time">{status['last_run']['time']}</div>
                <div class="status-detail">{status['last_run']['detail']}</div>
            </div>
            
            <div class="card">
                <h3>Next Scheduled</h3>
                <div class="status-time">{status['next_run']['time']}</div>
                <div class="status-detail">{status['next_run']['detail']}</div>
            </div>
        </div>
        
        <div class="card">
            <h3>System Health</h3>
            <div class="health-checks">
                {self.render_health_checks(status['health'])}
            </div>
        </div>
    </div>

    <script src="/static/js/status.js"></script>
</body>
</html>
        """
        self.send_html(html)
    
    def serve_api_data(self, data_type):
        """JSON API endpoint for real-time data"""
        try:
            if data_type == 'dashboard':
                data = self.get_dashboard_data()
            elif data_type == 'simulations':
                data = self.get_simulation_data()
            elif data_type == 'status':
                data = self.get_status_data()
            else:
                data = {"error": "Unknown data type"}
            
            self.send_json(data)
        except Exception as e:
            self.send_json({"error": str(e)})
    
    def serve_static(self, path):
        """Serve static files (CSS/JS)"""
        file_path = path[8:]  # Remove /static/
        if file_path == 'css/style.css':
            self.send_css(self.get_css())
        elif file_path == 'js/dashboard.js':
            self.send_js(self.get_dashboard_js())
        elif file_path == 'js/feed.js':
            self.send_js(self.get_feed_js())
        elif file_path == 'js/investigations.js':
            self.send_js(self.get_investigations_js())
        elif file_path == 'js/simulations.js':
            self.send_js(self.get_simulations_js())
        elif file_path == 'js/status.js':
            self.send_js(self.get_status_js())
        else:
            self.send_error(404)
    
    # Data loading methods
    
    def get_dashboard_data(self):
        """Collect dashboard overview data"""
        data = {
            'active_simulations': 0,
            'total_bankroll': 0,
            'recent_scrapes': 0,
            'last_scrape': 'None',
            'signals_today': 0,
            'investigated_today': 0,
            'total_pnl': 0,
            'total_pnl_pct': 0,
            'total_pnl_class': 'positive',
            'recent_activity': '<div class="empty-state">No recent activity</div>',
            'active_positions': '<div class="empty-state">No active positions</div>'
        }
        
        try:
            # Load active simulations
            active_path = os.path.join(DATA_DIR, "simulations", "active.json")
            if os.path.exists(active_path):
                with open(active_path) as f:
                    active = json.load(f)
                    positions = active.get('positions', [])
                    data['active_simulations'] = len(positions)
                    data['total_bankroll'] = active.get('bankroll_used', 0)
                    
                    # Calculate P&L
                    total_pnl = sum(pos.get('unrealized_pnl', 0) for pos in positions)
                    data['total_pnl'] = total_pnl
                    data['total_pnl_class'] = 'positive' if total_pnl >= 0 else 'negative'
                    
                    if data['total_bankroll'] > 0:
                        data['total_pnl_pct'] = (total_pnl / data['total_bankroll']) * 100
                    
                    # Render active positions
                    if positions:
                        pos_html = ""
                        for pos in positions:
                            pos_html += f"""
                            <div class="position-item">
                                <div class="position-asset">{pos.get('asset', 'Unknown')[:50]}</div>
                                <div class="position-pnl ${data['total_pnl_class']}">${pos.get('unrealized_pnl', 0):,.0f}</div>
                            </div>
                            """
                        data['active_positions'] = pos_html
            
            # Count investigations today
            inv_pattern = os.path.join(DATA_DIR, "investigations", "inv-*.json")
            today = datetime.now().strftime('%Y%m%d')
            today_invs = [f for f in glob.glob(inv_pattern) if today in os.path.basename(f)]
            data['investigated_today'] = len(today_invs)
            
            # Recent activity from investigations
            if today_invs:
                activity_html = ""
                for inv_file in today_invs[-5:]:  # Last 5
                    with open(inv_file) as f:
                        inv = json.load(f)
                        verdict = inv.get('investigation', {}).get('verdict', 'Unknown')
                        author = inv.get('source_post', {}).get('author', 'Unknown')
                        activity_html += f"""
                        <div class="activity-item">
                            <span class="activity-time">Today</span>
                            <span class="activity-text">Investigated {author}: {verdict}</span>
                        </div>
                        """
                data['recent_activity'] = activity_html
            
        except Exception as e:
            print(f"Dashboard data error: {e}")
        
        return data
    
    def get_latest_posts(self):
        """Get latest scraped posts with triage data"""
        posts = []
        try:
            # Find latest x-feed directory
            x_feed_pattern = os.path.join(X_FEED_DIR, "20*")
            x_feed_dirs = sorted(glob.glob(x_feed_pattern))
            
            if x_feed_dirs:
                latest_dir = x_feed_dirs[-1]
                posts_file = os.path.join(latest_dir, "posts.json")
                triage_file = os.path.join(latest_dir, "triage.json")
                
                # Load posts
                if os.path.exists(posts_file):
                    with open(posts_file) as f:
                        posts_data = json.load(f)
                        posts = posts_data.get('posts', [])
                
                # Load triage data and merge
                if os.path.exists(triage_file):
                    with open(triage_file) as f:
                        triage = json.load(f)
                        # Merge triage data with posts
                        for post in posts:
                            post_id = post.get('id')
                            for category, triaged_posts in triage.items():
                                if category == 'investigation_queue':
                                    continue
                                for tpost in triaged_posts:
                                    if tpost.get('id') == post_id:
                                        post['triage'] = {
                                            'category': category,
                                            'priority': tpost.get('priority'),
                                            'reason': tpost.get('reason')
                                        }
                                        break
        
        except Exception as e:
            print(f"Posts loading error: {e}")
        
        return posts[:50]  # Limit to last 50
    
    def get_investigations(self):
        """Get all investigation reports"""
        investigations = []
        try:
            inv_pattern = os.path.join(DATA_DIR, "investigations", "inv-*.json")
            for inv_file in sorted(glob.glob(inv_pattern), reverse=True):
                with open(inv_file) as f:
                    inv = json.load(f)
                    investigations.append(inv)
        except Exception as e:
            print(f"Investigations loading error: {e}")
        
        return investigations
    
    def get_simulation_data(self):
        """Get simulation data (active + history)"""
        data = {'active': {}, 'history': []}
        
        try:
            # Load active positions
            active_path = os.path.join(DATA_DIR, "simulations", "active.json")
            if os.path.exists(active_path):
                with open(active_path) as f:
                    data['active'] = json.load(f)
            
            # Load history if it exists
            history_path = os.path.join(DATA_DIR, "simulations", "history.json")
            if os.path.exists(history_path):
                with open(history_path) as f:
                    data['history'] = json.load(f)
        
        except Exception as e:
            print(f"Simulation data error: {e}")
        
        return data
    
    def get_status_data(self):
        """Get pipeline status information"""
        status = {
            'chrome': {'status': 'Unknown', 'class': 'unknown', 'detail': 'Checking...'},
            'last_run': {'time': 'Unknown', 'detail': 'No recent runs found'},
            'next_run': {'time': 'Unknown', 'detail': 'Check schedule in config.json'},
            'health': []
        }
        
        try:
            # Check Chrome debug port
            import urllib.request
            try:
                urllib.request.urlopen('http://127.0.0.1:9222/json', timeout=2)
                status['chrome'] = {
                    'status': 'Running',
                    'class': 'healthy',
                    'detail': 'Debug port 9222 accessible'
                }
            except:
                status['chrome'] = {
                    'status': 'Down',
                    'class': 'error',
                    'detail': 'Port 9222 not accessible'
                }
            
            # Check for recent pipeline runs
            x_feed_pattern = os.path.join(X_FEED_DIR, "20*")
            x_feed_dirs = sorted(glob.glob(x_feed_pattern))
            if x_feed_dirs:
                latest = os.path.basename(x_feed_dirs[-1])
                # Parse timestamp from dirname (format: 20260207-234451)
                try:
                    dt = datetime.strptime(latest, '%Y%m%d-%H%M%S')
                    status['last_run'] = {
                        'time': dt.strftime('%Y-%m-%d %H:%M:%S'),
                        'detail': f"Scraped data in {latest}"
                    }
                except:
                    status['last_run'] = {
                        'time': latest,
                        'detail': 'Found recent scrape data'
                    }
        
        except Exception as e:
            print(f"Status check error: {e}")
        
        return status
    
    # Rendering methods
    
    def render_posts(self, posts):
        """Render feed posts with triage status"""
        if not posts:
            return '<div class="empty-state">No posts found</div>'
        
        html = ""
        for post in posts:
            triage = post.get('triage', {})
            category = triage.get('category', 'unknown')
            priority = triage.get('priority', 0)
            
            # Color coding based on triage category
            if category == 'high_value':
                status_class = 'high-value'
                status_text = f'High Value (Priority: {priority})'
            elif category == 'worth_investigating':
                status_class = 'investigate'
                status_text = f'Worth Investigating (Priority: {priority})'
            elif category == 'dismissed':
                status_class = 'dismissed'
                status_text = 'Dismissed'
            else:
                status_class = 'unknown'
                status_text = 'Not Triaged'
            
            html += f"""
            <div class="post-item">
                <div class="post-header">
                    <div class="post-author">{post.get('author', 'Unknown')}</div>
                    <div class="post-status {status_class}">{status_text}</div>
                </div>
                <div class="post-content">{post.get('text', '')[:200]}...</div>
                <div class="post-footer">
                    <span class="post-time">{post.get('timestamp', 'Unknown time')}</span>
                    <span class="post-metrics">{post.get('likes', 0)} likes • {post.get('retweets', 0)} retweets</span>
                </div>
            </div>
            """
        
        return html
    
    def render_investigations(self, investigations):
        """Render investigation reports with rich links"""
        if not investigations:
            return '<div class="empty-state">No investigations found</div>'
        
        html = ""
        for inv in investigations:
            investigation = inv.get('investigation', {})
            verdict = investigation.get('verdict', 'Unknown')
            risk_score = investigation.get('risk_assessment', {}).get('score', 0)
            risk_notes = investigation.get('risk_assessment', {}).get('notes', [])
            source = inv.get('source_post', {})
            verified = investigation.get('verified_data', {})
            claim_vs = investigation.get('claim_vs_reality', {})
            profile_url = investigation.get('profile_url', '')
            strategy_notes = investigation.get('strategy_notes', '')
            suggested = inv.get('suggested_simulation', {})
            
            verdict_class = 'verified' if 'VERIFIED' in verdict else 'failed'
            
            # Build links section
            links_html = '<div class="investigation-links">'
            if source.get('url'):
                links_html += f'<a href="{source["url"]}" target="_blank" class="inv-link">📝 Original Post</a>'
            if source.get('author'):
                author = source["author"].replace("@", "")
                links_html += f'<a href="https://x.com/{author}" target="_blank" class="inv-link">🐦 {source["author"]} on X</a>'
            if profile_url:
                links_html += f'<a href="{profile_url}" target="_blank" class="inv-link">👤 Polymarket Profile</a>'
            # Extract wallet if present in the investigation data
            wallet = inv.get('investigation', {}).get('wallet_address', '')
            if not wallet:
                # Try to find it in verified data or elsewhere
                for key, val in verified.items():
                    if isinstance(val, str) and val.startswith('0x'):
                        wallet = val
                        break
            if wallet:
                links_html += f'<a href="https://polygonscan.com/address/{wallet}" target="_blank" class="inv-link">🔗 Wallet on Polygonscan</a>'
            links_html += '</div>'
            
            # Build verified data section
            verified_html = ''
            if verified:
                verified_html = '<div class="investigation-verified"><h4>Verified Data</h4><div class="verified-grid">'
                for key, val in verified.items():
                    label = key.replace('_', ' ').title()
                    verified_html += f'<div class="verified-item"><span class="verified-label">{label}</span><span class="verified-value">{val}</span></div>'
                verified_html += '</div></div>'
            
            # Build claim vs reality section
            claim_html = ''
            if claim_vs:
                claim_html = '<div class="investigation-claims"><h4>Claim vs Reality</h4>'
                for key, val in claim_vs.items():
                    label = key.replace('_', ' ').title()
                    claim_html += f'<div class="claim-row"><span class="claim-label">{label}</span><span class="claim-value">{val}</span></div>'
                claim_html += '</div>'
            
            # Risk notes
            risk_html = ''
            if risk_notes:
                risk_html = '<div class="investigation-risk"><h4>Risk Assessment</h4><ul>'
                for note in risk_notes:
                    risk_html += f'<li>{note}</li>'
                risk_html += '</ul></div>'
            
            # Strategy notes
            strategy_html = ''
            if strategy_notes:
                strategy_html = f'<div class="investigation-strategy"><h4>Strategy Notes</h4><p>{strategy_notes}</p></div>'
            
            html += f"""
            <div class="investigation-item">
                <div class="investigation-header">
                    <div class="investigation-author">{source.get('author', 'Unknown')}</div>
                    <div class="investigation-verdict {verdict_class}">{verdict}</div>
                </div>
                <div class="investigation-claim">"{source.get('claim', 'No claim')}"</div>
                {links_html}
                {verified_html}
                {claim_html}
                <div class="investigation-score">Risk Score: <strong>{risk_score}/10</strong></div>
                {risk_html}
                {strategy_html}
            </div>
            """
        
        return html
    
    def render_active_positions(self, active_data):
        """Render active trading positions"""
        positions = active_data.get('positions', [])
        if not positions:
            return '<div class="empty-state">No active positions</div>'
        
        html = ""
        for pos in positions:
            pnl = pos.get('unrealized_pnl', 0)
            pnl_class = 'positive' if pnl >= 0 else 'negative'
            
            html += f"""
            <div class="position-item">
                <div class="position-header">
                    <div class="position-asset">{pos.get('asset', 'Unknown')}</div>
                    <div class="position-pnl {pnl_class}">${pnl:,.0f}</div>
                </div>
                <div class="position-details">
                    <span>Size: ${pos.get('size', 0):,.0f}</span>
                    <span>Entry: ${pos.get('entry_price', 0):.2f}</span>
                    <span>Current: ${pos.get('current_price', 0):.2f}</span>
                </div>
                <div class="position-strategy">{pos.get('strategy', 'Unknown strategy')}</div>
            </div>
            """
        
        return html
    
    def render_performance_metrics(self, sim_data):
        """Render performance metrics"""
        active = sim_data.get('active', {})
        positions = active.get('positions', [])
        
        if not positions:
            return '<div class="empty-state">No performance data</div>'
        
        total_pnl = sum(pos.get('unrealized_pnl', 0) for pos in positions)
        bankroll = active.get('bankroll_used', 1)
        pnl_pct = (total_pnl / bankroll) * 100 if bankroll > 0 else 0
        
        return f"""
        <div class="metric-row">
            <div class="metric-label">Total P&L</div>
            <div class="metric-value ${'positive' if total_pnl >= 0 else 'negative'}">${total_pnl:,.0f}</div>
        </div>
        <div class="metric-row">
            <div class="metric-label">Return %</div>
            <div class="metric-value ${'positive' if pnl_pct >= 0 else 'negative'}">{pnl_pct:+.1f}%</div>
        </div>
        <div class="metric-row">
            <div class="metric-label">Bankroll Used</div>
            <div class="metric-value">${bankroll:,.0f}</div>
        </div>
        """
    
    def render_trade_history(self, history):
        """Render trade history"""
        if not history:
            return '<div class="empty-state">No trade history</div>'
        
        html = ""
        for trade in history[-10:]:  # Last 10 trades
            pnl = trade.get('realized_pnl', 0)
            pnl_class = 'positive' if pnl >= 0 else 'negative'
            
            html += f"""
            <div class="trade-item">
                <div class="trade-header">
                    <div class="trade-asset">{trade.get('asset', 'Unknown')}</div>
                    <div class="trade-pnl {pnl_class}">${pnl:,.0f}</div>
                </div>
                <div class="trade-details">
                    <span>Closed: {trade.get('closed_at', 'Unknown')}</span>
                    <span>Duration: {trade.get('duration_hours', 0):.1f}h</span>
                </div>
            </div>
            """
        
        return html
    
    def render_health_checks(self, health_data):
        """Render system health checks"""
        return '''
        <div class="health-item healthy">
            <div class="health-name">Data Directory</div>
            <div class="health-status">OK</div>
        </div>
        <div class="health-item healthy">
            <div class="health-name">Config File</div>
            <div class="health-status">OK</div>
        </div>
        '''
    
    # Static file content
    
    def get_css(self):
        """Main stylesheet"""
        return """
/* Feed Hunter Portal - Dark Theme */
:root {
    --bg-primary: #0d1117;
    --bg-secondary: #161b22;
    --bg-tertiary: #21262d;
    --text-primary: #f0f6fc;
    --text-secondary: #8b949e;
    --border-color: #30363d;
    --accent-blue: #58a6ff;
    --success-green: #3fb950;
    --warning-orange: #ffab40;
    --error-red: #f85149;
    --positive-green: #3fb950;
    --negative-red: #f85149;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: var(--bg-primary);
    color: var(--text-primary);
    line-height: 1.5;
    min-height: 100vh;
}

/* Navigation */
.navbar {
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
    padding: 1rem 2rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.nav-brand {
    font-size: 1.5rem;
    font-weight: bold;
    color: var(--accent-blue);
}

.nav-links {
    display: flex;
    gap: 2rem;
}

.nav-links a {
    color: var(--text-secondary);
    text-decoration: none;
    padding: 0.5rem 1rem;
    border-radius: 6px;
    transition: all 0.2s;
}

.nav-links a:hover {
    color: var(--text-primary);
    background: var(--bg-tertiary);
}

.nav-links a.active {
    color: var(--accent-blue);
    background: var(--bg-tertiary);
}

/* Container */
.container {
    max-width: 1400px;
    margin: 0 auto;
    padding: 2rem;
}

/* Cards */
.card {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 1.5rem;
    margin-bottom: 1.5rem;
}

.card h3 {
    color: var(--text-primary);
    margin-bottom: 1rem;
    font-size: 1.1rem;
}

/* Grid layouts */
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1.5rem;
    margin-bottom: 2rem;
}

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
    gap: 1.5rem;
}

/* Metrics */
.metric-large {
    font-size: 2.5rem;
    font-weight: bold;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.metric-small {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.metric-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--border-color);
}

.metric-row:last-child {
    border-bottom: none;
}

.metric-label {
    color: var(--text-secondary);
}

.metric-value {
    font-weight: bold;
}

.positive {
    color: var(--positive-green) !important;
}

.negative {
    color: var(--negative-red) !important;
}

/* Posts */
.feed-posts {
    display: grid;
    gap: 1rem;
}

.post-item {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 1rem;
}

.post-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
}

.post-author {
    font-weight: bold;
    color: var(--text-primary);
}

.post-status {
    padding: 0.25rem 0.75rem;
    border-radius: 12px;
    font-size: 0.8rem;
    font-weight: bold;
}

.post-status.high-value {
    background: var(--success-green);
    color: #000;
}

.post-status.investigate {
    background: var(--warning-orange);
    color: #000;
}

.post-status.dismissed {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
}

.post-status.unknown {
    background: var(--bg-tertiary);
    color: var(--text-secondary);
}

.post-content {
    color: var(--text-primary);
    margin-bottom: 0.75rem;
    line-height: 1.4;
}

.post-footer {
    display: flex;
    justify-content: space-between;
    color: var(--text-secondary);
    font-size: 0.85rem;
}

/* Investigations */
.investigation-item {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 1rem;
    margin-bottom: 1rem;
}

.investigation-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.75rem;
}

.investigation-author {
    font-weight: bold;
    color: var(--text-primary);
}

.investigation-verdict {
    padding: 0.25rem 0.75rem;
    border-radius: 12px;
    font-size: 0.8rem;
    font-weight: bold;
}

.investigation-verdict.verified {
    background: var(--success-green);
    color: #000;
}

.investigation-verdict.failed {
    background: var(--error-red);
    color: #fff;
}

.investigation-claim {
    color: var(--text-primary);
    margin-bottom: 0.5rem;
    font-style: italic;
}

.investigation-score {
    color: var(--text-secondary);
    font-size: 0.9rem;
    margin-bottom: 0.75rem;
}

.investigation-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0.75rem 0;
}

.inv-link {
    display: inline-block;
    padding: 0.35rem 0.75rem;
    background: var(--bg-tertiary);
    color: var(--accent-blue);
    text-decoration: none;
    border-radius: 6px;
    font-size: 0.85rem;
    border: 1px solid var(--border-color);
    transition: all 0.2s;
}

.inv-link:hover {
    background: var(--border-color);
    color: var(--text-primary);
}

.investigation-verified, .investigation-claims, .investigation-risk, .investigation-strategy {
    margin: 1rem 0;
    padding: 1rem;
    background: var(--bg-tertiary);
    border-radius: 6px;
}

.investigation-verified h4, .investigation-claims h4, .investigation-risk h4, .investigation-strategy h4 {
    color: var(--accent-blue);
    margin-bottom: 0.75rem;
    font-size: 0.95rem;
}

.verified-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 0.5rem;
}

.verified-item {
    display: flex;
    flex-direction: column;
    padding: 0.5rem;
    background: var(--bg-secondary);
    border-radius: 4px;
}

.verified-label {
    color: var(--text-secondary);
    font-size: 0.8rem;
}

.verified-value {
    color: var(--text-primary);
    font-weight: bold;
    font-size: 1rem;
}

.claim-row {
    display: flex;
    justify-content: space-between;
    padding: 0.4rem 0;
    border-bottom: 1px solid var(--border-color);
}

.claim-row:last-child { border-bottom: none; }

.claim-label {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.claim-value {
    color: var(--text-primary);
    font-size: 0.9rem;
    text-align: right;
    max-width: 60%;
}

.investigation-risk ul {
    list-style: none;
    padding: 0;
}

.investigation-risk li {
    padding: 0.3rem 0;
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.investigation-risk li::before {
    content: "⚠️ ";
}

.investigation-strategy p {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.5;
}

/* Positions */
.position-item {
    background: var(--bg-tertiary);
    border-radius: 6px;
    padding: 1rem;
    margin-bottom: 0.75rem;
}

.position-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
}

.position-asset {
    font-weight: bold;
    color: var(--text-primary);
}

.position-pnl {
    font-weight: bold;
}

.position-details {
    display: flex;
    gap: 1rem;
    color: var(--text-secondary);
    font-size: 0.9rem;
    margin-bottom: 0.5rem;
}

.position-strategy {
    color: var(--text-secondary);
    font-size: 0.85rem;
    font-style: italic;
}

/* Status indicators */
.status-indicator {
    font-size: 1.5rem;
    font-weight: bold;
    margin-bottom: 0.5rem;
}

.status-indicator.healthy {
    color: var(--success-green);
}

.status-indicator.error {
    color: var(--error-red);
}

.status-indicator.unknown {
    color: var(--warning-orange);
}

.status-time {
    font-size: 1.2rem;
    font-weight: bold;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.status-detail {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

.health-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem;
    background: var(--bg-tertiary);
    border-radius: 6px;
    margin-bottom: 0.5rem;
}

/* Activity feed */
.activity-item {
    display: flex;
    gap: 1rem;
    padding: 0.75rem;
    border-bottom: 1px solid var(--border-color);
}

.activity-item:last-child {
    border-bottom: none;
}

.activity-time {
    color: var(--text-secondary);
    font-size: 0.85rem;
    flex-shrink: 0;
}

.activity-text {
    color: var(--text-primary);
    font-size: 0.9rem;
}

/* Empty states */
.empty-state {
    text-align: center;
    color: var(--text-secondary);
    padding: 2rem;
    font-style: italic;
}

/* Buttons */
button {
    background: var(--accent-blue);
    color: #fff;
    border: none;
    padding: 0.5rem 1rem;
    border-radius: 6px;
    font-size: 0.9rem;
    cursor: pointer;
    transition: background 0.2s;
}

button:hover {
    background: #4493e1;
}

/* Mobile responsiveness */
@media (max-width: 768px) {
    .navbar {
        flex-direction: column;
        gap: 1rem;
        padding: 1rem;
    }
    
    .nav-links {
        gap: 1rem;
    }
    
    .container {
        padding: 1rem;
    }
    
    .cards {
        grid-template-columns: 1fr;
    }
    
    .grid {
        grid-template-columns: 1fr;
    }
    
    .position-details {
        flex-direction: column;
        gap: 0.25rem;
    }
    
    .post-footer {
        flex-direction: column;
        gap: 0.25rem;
    }
}
        """
    
    def get_dashboard_js(self):
        """Dashboard JavaScript"""
        return """
// Dashboard real-time updates
let updateInterval;

function startDashboardUpdates() {
    updateInterval = setInterval(updateDashboard, 30000); // 30 seconds
}

function updateDashboard() {
    fetch('/api/data?type=dashboard')
        .then(response => response.json())
        .then(data => {
            if (data.error) {
                console.error('Dashboard update error:', data.error);
                return;
            }
            
            // Update key metrics
            updateElement('.metric-large', data.total_pnl, (el, val) => {
                el.textContent = `$${val.toLocaleString()}`;
                el.className = `metric-large ${data.total_pnl_class}`;
            });
            
            // Update other metrics as needed
        })
        .catch(error => console.error('Dashboard update failed:', error));
}

function updateElement(selector, value, updater) {
    const elements = document.querySelectorAll(selector);
    elements.forEach(el => {
        if (updater) {
            updater(el, value);
        } else {
            el.textContent = value;
        }
    });
}

// Start updates when page loads
document.addEventListener('DOMContentLoaded', startDashboardUpdates);

// Stop updates when page unloads
window.addEventListener('beforeunload', () => {
    if (updateInterval) clearInterval(updateInterval);
});
        """
    
    def get_feed_js(self):
        return "// Feed view JavaScript - placeholder"
    
    def get_investigations_js(self):
        return """
function showInvestigationDetail(invId) {
    alert('Investigation detail view for: ' + invId);
    // TODO: Implement modal or detail view
}
        """
    
    def get_simulations_js(self):
        return "// Simulations JavaScript - placeholder"
    
    def get_status_js(self):
        return """
// Auto-refresh status page
setInterval(() => {
    location.reload();
}, 60000); // 1 minute
        """
    
    # Response helpers
    
    def send_html(self, content):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(content.encode())
    
    def send_css(self, content):
        self.send_response(200)
        self.send_header('Content-type', 'text/css')
        self.end_headers()
        self.wfile.write(content.encode())
    
    def send_js(self, content):
        self.send_response(200)
        self.send_header('Content-type', 'application/javascript')
        self.end_headers()
        self.wfile.write(content.encode())
    
    def send_json(self, data):
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(data).encode())
    
    def log_message(self, format, *args):
        # Suppress default logging
        pass

def main():
    """Start the Feed Hunter portal server"""
    print(f"🖤 Feed Hunter Portal starting on localhost:{PORT}")
    print(f"📊 Dashboard: http://localhost:{PORT}/")
    print(f"🔍 Status: http://localhost:{PORT}/status")
    print("")
    
    try:
        server = ThreadedHTTPServer(('0.0.0.0', PORT), FeedHunterHandler)
        server.serve_forever()
    except KeyboardInterrupt:
        print("\n🛑 Portal stopped")
    except Exception as e:
        print(f"❌ Server error: {e}")

if __name__ == "__main__":
    main()