import yfinance as yf
import pandas as pd
import numpy as np
import requests
from datetime import datetime
import os
import re
import urllib.request
import urllib.parse
import xml.etree.ElementTree as ET

from config import TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID
from scanner_common import (
    calculate_rsi,
    detect_bullish_engulfing,
    detect_hammer,
    detect_liquidity_sweep,
    detect_volume_spike,
    detect_volume_ratio,
    detect_rsi_bullish_divergence,
    drop_incomplete_last_bar,
    make_verdict,
    regime_min_score,
    rolling_high,
)

# =========================================================
# CONFIGURATION
# =========================================================
REGIME_FILTER_MODE = "block"
SIGNAL_LOOKBACK_DAYS = 3  # ฝั่ง US ใช้ 3 วัน (ตามระบบเดิม)
MIN_SCORE_BASE = 2

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DASHBOARD_FILE = os.path.join(BASE_DIR, "dashboard.html")
TUNNEL_LOG = os.path.join(BASE_DIR, "tunnel.log")

# =========================================================
# UNIVERSE: S&P 500 / NASDAQ QUALITY BLUE CHIPS
# =========================================================
UNIVERSE_US = [
    # เทคโนโลยี (Tech)
    "AAPL", "MSFT", "GOOGL", "AMZN", "META", "NVDA", "TSLA", "NFLX",
    "AMD", "CRM", "ADBE", "INTC", "QCOM", "AVGO", "AMAT", "LRCX",
    # ค้าปลีกและอุปโภค (Consumer)
    "COST", "WMT", "NKE", "SBUX", "MCD", "DIS", "KO", "PEP", "PG",
    # การเงิน (Finance)
    "V", "MA", "JPM", "BAC", "PYPL",
    # การแพทย์ (Healthcare)
    "LLY", "UNH", "JNJ", "PFE", "ABBV", "MRK",
    # อุตสาหกรรมและพลังงาน (Industrial & Energy)
    "CAT", "BA", "DE", "XOM", "CVX"
]

# =========================================================
# REGIME CALCULATION (S&P 500 vs EMA200)
# =========================================================
def check_sp500_regime():
    try:
        idx = yf.Ticker("^GSPC").history(period="1y")
        idx, _ = drop_incomplete_last_bar(idx, "US")
        if idx.empty:
            return "UNKNOWN", 0, 0, 0
        idx['EMA200'] = idx['Close'].ewm(span=200, adjust=False).mean()
        latest_close = idx['Close'].iloc[-1]
        latest_ema200 = idx['EMA200'].iloc[-1]
        pct_diff = ((latest_close - latest_ema200) / latest_ema200) * 100
        is_bull = latest_close > latest_ema200
        return ("BULL", latest_close, latest_ema200, pct_diff) if is_bull else ("BEAR", latest_close, latest_ema200, pct_diff)
    except Exception:
        return "UNKNOWN", 0, 0, 0

# =========================================================
# NEWS FETCHER & TECHNICAL DIAGNOSIS
# =========================================================
def fetch_us_news(symbol):
    """Fetch English financial news headlines via Google News RSS"""
    try:
        query = urllib.parse.quote(f"{symbol} stock")
        url = f"https://news.google.com/rss/search?q={query}&hl=en-US&gl=US&ceid=US:en"
        req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'})
        with urllib.request.urlopen(req, timeout=5) as resp:
            xml_data = resp.read()
        root = ET.fromstring(xml_data)
        items = root.findall('./channel/item')
        headlines = []
        for it in items[:3]:
            title = it.find('title').text
            title = re.sub(r"\s*-\s*[^-]+$", "", title)
            headlines.append(title.strip())
        return " | ".join(headlines) if headlines else "No significant negative news"
    except Exception:
        return "Market conditions normal"


def ask_ai_us(symbol, price, drawdown, rsi, news_text,
              sweep=False, pa=False, ema=False, score=0,
              volume_spike=False, rsi_divergence=False, vol_ratio=1.0):
    """สร้างคำอธิบายแบบ rule-based (ไม่ใช้ AI) — ผลคงที่ทุกครั้ง"""
    return make_verdict(drawdown, rsi, sweep, pa, ema, score, news_text,
                        volume_spike, rsi_divergence, vol_ratio)


def send_telegram_alert(text):
    url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
    payload = {
        "chat_id": TELEGRAM_CHAT_ID,
        "text": text,
        "parse_mode": "Markdown"
    }
    try:
        res = requests.post(url, data=payload, timeout=10)
        return res.json()
    except Exception as e:
        print(f"Error sending telegram: {e}")
        return None


def get_live_tunnel_url():
    if os.path.exists(TUNNEL_LOG):
        try:
            with open(TUNNEL_LOG, "r") as f:
                matches = re.findall(r"https://[a-zA-Z0-9-]+\.trycloudflare\.com", f.read())
                if matches:
                    return matches[-1]
        except Exception:
            pass
    return None


# =========================================================
# DASHBOARD GENERATOR (US)
# =========================================================
SECTOR_MAP_US = {
    "AAPL": "เทคโนโลยี (Apple)", "MSFT": "ซอฟต์แวร์ (Microsoft)", "GOOGL": "อินเทอร์เน็ต (Alphabet)",
    "AMZN": "อีคอมเมิร์ซ (Amazon)", "META": "โซเชียลมีเดีย (Meta)", "NVDA": "ชิป AI (Nvidia)",
    "TSLA": "ยานยนต์ไฟฟ้า (Tesla)", "NFLX": "สตรีมมิ่ง (Netflix)",
    "AMD": "ชิปประมวลผล (AMD)", "CRM": "CRM (Salesforce)", "ADBE": "ซอฟต์แวร์ครีเอทีฟ (Adobe)",
    "INTC": "ชิปเซมิคอนดักเตอร์ (Intel)", "QCOM": "ชิปมือถือ (Qualcomm)", "AVGO": "ชิป (Broadcom)",
    "AMAT": "อุปกรณ์เซมิคอนดักเตอร์ (Applied)", "LRCX": "อุปกรณ์เซมิคอนดักเตอร์ (Lam)",
    "COST": "ค้าปลีก (Costco)", "WMT": "ค้าปลีก (Walmart)", "NKE": "เครื่องกีฬา (Nike)",
    "SBUX": "กาแฟ (Starbucks)", "MCD": "ฟาสต์ฟู้ด (McDonald's)", "DIS": "มีเดีย/บันเทิง (Disney)",
    "KO": "เครื่องดื่ม (Coca-Cola)", "PEP": "เครื่องดื่ม/อาหาร (PepsiCo)", "PG": "อุปโภค (Procter & Gamble)",
    "V": "การเงินดิจิทัล (Visa)", "MA": "การเงินดิจิทัล (Mastercard)", "JPM": "ธนาคาร (JPMorgan)",
    "BAC": "ธนาคาร (Bank of America)", "PYPL": "การเงินดิจิทัล (PayPal)",
    "LLY": "ยา (Eli Lilly)", "UNH": "ประกันสุขภาพ (UnitedHealth)", "JNJ": "ยา/เวชภัณฑ์ (J&J)",
    "PFE": "ยา (Pfizer)", "ABBV": "ยา (AbbVie)", "MRK": "ยา (Merck)",
    "CAT": "เครื่องจักรหนัก (Caterpillar)", "BA": "อากาศยาน (Boeing)", "DE": "เครื่องจักรเกษตร (Deere)",
    "XOM": "พลังงาน (ExxonMobil)", "CVX": "พลังงาน (Chevron)"
}

APPLE_ACCENTS = [
    ("from-emerald-400 to-teal-500", "bg-emerald-50 text-emerald-700 border-emerald-200"),
    ("from-sky-400 to-blue-500", "bg-sky-50 text-sky-700 border-sky-200"),
    ("from-indigo-400 to-violet-500", "bg-indigo-50 text-indigo-700 border-indigo-200"),
    ("from-purple-400 to-fuchsia-500", "bg-purple-50 text-purple-700 border-purple-200"),
    ("from-amber-400 to-orange-500", "bg-amber-50 text-amber-700 border-amber-200"),
    ("from-rose-400 to-pink-500", "bg-rose-50 text-rose-700 border-rose-200")
]


def generate_dashboard_us_html(regime, spx_close, spx_ema, pct_diff, grade_a, watchlist):
    timestamp_str = datetime.now().strftime("%d %b %Y | %H:%M น.")
    count_top = len([s for s in grade_a if s['score'] >= 4])

    cards_html = ""
    for idx, s in enumerate(grade_a):
        clean_sym = s['symbol']
        sector = SECTOR_MAP_US.get(s['symbol'], "S&P 500 Blue Chip")
        score = s['score']
        is_top = (score >= 4)
        grad_color, pill_color = APPLE_ACCENTS[idx % len(APPLE_ACCENTS)]

        if is_top:
            star_badge = """
    <span class="inline-flex items-center gap-1.5 px-3.5 py-1 rounded-full text-sm font-semibold bg-amber-500/15 text-amber-900 border border-amber-300/80 shadow-sm">
      <span class="text-amber-500">★</span> สัญญาณครบ 4/4 (Prime Setup)
    </span>"""
            card_ring = "ring-2 ring-amber-400/50 shadow-[0_12px_36px_rgba(245,158,11,0.12)]"
        else:
            star_badge = f"""
    <span class="inline-flex items-center gap-1.5 px-3.5 py-1 rounded-full text-sm font-medium bg-sky-500/10 text-sky-900 border border-sky-200/80">
      <span class="text-sky-500">●</span> ผ่าน {score}/4 สัญญาณ
    </span>"""
            card_ring = "border border-white/60 shadow-[0_8px_30px_rgba(0,0,0,0.04)]"

        cards_html += f"""
    <div class="stock-card group relative rounded-[2rem] p-5 sm:p-6 bg-white/80 backdrop-blur-2xl transition-all duration-300 hover:-translate-y-1.5 hover:shadow-[0_20px_45px_rgba(0,113,227,0.12)] {card_ring}"
         data-symbol="{clean_sym}" data-score="{score}">
      <div class="flex items-start justify-between gap-3 mb-4">
        <div class="flex items-center gap-3 min-w-0">
          <div class="w-[52px] h-[52px] shrink-0 rounded-2xl bg-gradient-to-tr {grad_color} text-white font-bold flex items-center justify-center text-lg tracking-tight shadow-md shadow-blue-500/20">
            {clean_sym[:4]}
          </div>
          <div class="min-w-0">
            <h3 class="font-bold text-slate-900 text-2xl tracking-tight truncate group-hover:text-[#0071e3] transition">{clean_sym}</h3>
            <p class="text-xs sm:text-sm text-slate-500 font-medium truncate mt-0.5">{sector}</p>
          </div>
        </div>
        <div class="text-right shrink-0">
          <div class="text-2xl sm:text-3xl font-extrabold text-slate-900 tracking-tight">${s['price']:.2f}</div>
          <div class="flex items-center justify-end gap-1.5 mt-1">
            <span class="text-xs font-semibold px-2 py-0.5 rounded-full bg-rose-500/10 text-rose-700 border border-rose-200">-{s['drawdown']:.1f}%</span>
            <span class="text-xs font-semibold px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-700 border border-emerald-200">RSI {s['rsi']:.1f}</span>
          </div>
        </div>
      </div>
      <div class="mb-4">{star_badge}</div>
      <div class="grid grid-cols-4 gap-1.5 py-2.5 px-3 bg-slate-100/70 backdrop-blur-md rounded-2xl text-xs sm:text-sm font-semibold text-slate-700 mb-4 border border-slate-200/50">
        <div class="flex items-center justify-center gap-1 {'text-emerald-600 font-bold' if s['sweep'] else 'text-slate-400'}">
          <span>{'✓' if s['sweep'] else '—'}</span> <span class="truncate">SMC Sweep</span>
        </div>
        <div class="flex items-center justify-center gap-1 {'text-emerald-600 font-bold' if s['pa'] else 'text-slate-400'}">
          <span>{'✓' if s['pa'] else '—'}</span> <span class="truncate">Price Action</span>
        </div>
        <div class="flex items-center justify-center gap-1 {'text-emerald-600 font-bold' if s['ema'] else 'text-slate-400'}">
          <span>{'✓' if s['ema'] else '—'}</span> <span class="truncate">เหนือ EMA9</span>
        </div>
        <div class="flex items-center justify-center gap-1 {'text-emerald-600 font-bold' if s.get('volume_spike') else 'text-slate-400'}">
          <span>{'✓' if s.get('volume_spike') else '—'}</span> <span class="truncate">Volume {s.get('vol_ratio', 1.0):.1f}x</span>
        </div>
      </div>
      <div class="grid grid-cols-3 gap-2 mb-4">
        <div class="rounded-xl px-3 py-2 bg-slate-50 border border-slate-200/70 text-center">
          <div class="text-[11px] font-semibold text-slate-400 uppercase tracking-wide">จุดเข้า</div>
          <div class="text-base font-bold text-slate-900">${s['price']:.2f}</div>
        </div>
        <div class="rounded-xl px-3 py-2 bg-rose-50 border border-rose-200/70 text-center">
          <div class="text-[11px] font-semibold text-rose-400 uppercase tracking-wide">ตัดขาดทุน</div>
          <div class="text-base font-bold text-rose-700">${s.get('stop_loss', 0):.2f}</div>
          <div class="text-[11px] font-medium text-rose-500">{s.get('sl_pct', 0):.1f}%</div>
        </div>
        <div class="rounded-xl px-3 py-2 bg-emerald-50 border border-emerald-200/70 text-center">
          <div class="text-[11px] font-semibold text-emerald-500 uppercase tracking-wide">เป้าขาย</div>
          <div class="text-base font-bold text-emerald-700">${s.get('take_profit', 0):.2f}</div>
          <div class="text-[11px] font-medium text-emerald-600">+{s.get('tp_pct', 0):.1f}%</div>
        </div>
      </div>
      <div class="rounded-2xl p-4 bg-gradient-to-br from-indigo-50/80 via-white/70 to-blue-50/60 border border-blue-100/80 backdrop-blur-md mb-4 shadow-sm">
        <div class="flex items-center gap-2 mb-2 text-xs sm:text-sm font-bold text-[#0071e3]">
          <span>🧠</span> <span>วิเคราะห์ตามสัญญาณเทคนิค:</span>
        </div>
        <p class="text-sm sm:text-base text-slate-700 leading-relaxed font-medium">{s.get('ai_verdict', 'ย่อตัวตามภาวะตลาดรวม')}</p>
        <div class="mt-2.5 pt-2 border-t border-blue-100/60 text-xs text-slate-500 italic">
          📰 ข่าวล่าสุด: {s.get('news_summary', '')[:90]}...
        </div>
      </div>
      {'<div class="mb-4 px-3 py-2 rounded-xl bg-emerald-50/80 border border-emerald-200/60 text-sm font-semibold text-emerald-700">📈 RSI Divergence detected — ขาลงอ่อนแรง มีโอกาสกลับตัว</div>' if s.get('rsi_divergence') else ''}
    </div>"""

    watchlist_html = ""
    for w in watchlist:
        clean_w = w['symbol']
        w_sector = SECTOR_MAP_US.get(w['symbol'], 'S&P 500')
        watchlist_html += f"""
    <div class="flex items-center justify-between p-4 rounded-2xl bg-white/60 hover:bg-white/90 border border-slate-200/60 transition shadow-sm">
      <div class="flex items-center gap-3">
        <div class="w-10 h-10 rounded-xl bg-slate-100 text-slate-700 font-bold flex items-center justify-center text-sm">{clean_w[:4]}</div>
        <div>
          <div class="font-bold text-slate-900 text-base sm:text-lg">{clean_w}</div>
          <div class="text-xs sm:text-sm text-slate-500 font-medium">{w_sector}</div>
        </div>
      </div>
      <div class="text-right">
        <div class="text-base sm:text-lg font-bold text-slate-800">${w['price']:.2f}</div>
        <div class="text-xs sm:text-sm font-semibold text-rose-600">-{w['drawdown']:.1f}% (RSI {w['rsi']:.1f})</div>
      </div>
    </div>"""

    empty_html = """
    <div class="col-span-full py-16 px-8 rounded-[2.5rem] bg-white/60 backdrop-blur-xl border border-white/80 text-center">
      <div class="text-5xl mb-4">🛡️</div>
      <h3 class="text-2xl font-bold text-slate-800 mb-2">ยังไม่มีหุ้นเกรด A+ ครบทุกเงื่อนไข</h3>
      <p class="text-slate-500 max-w-lg mx-auto text-base">ระบบสแกน S&P 500 แล้ว ไม่พบหุ้นที่เข้าเกณฑ์</p>
    </div>"""

    regime_color = "bg-emerald-500 shadow-emerald-500" if regime == "BULL" else "bg-amber-500 shadow-amber-500"
    regime_text = f"BULL (+{pct_diff:.1f}% เหนือ EMA200)" if regime == "BULL" else f"BEAR ({pct_diff:.1f}% ต่ำกว่า EMA200)"

    full_html = f"""<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>S&amp;P 500 Radar Terminal</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    body {{ font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Sukhumvit Set", sans-serif; background: radial-gradient(circle at 10% 20%, rgba(216, 241, 255, 0.8) 0%, rgba(255, 245, 235, 0.7) 45%, rgba(238, 242, 255, 0.8) 100%); min-height: 100vh; color: #1d1d1f; }}
    .traffic-dot {{ width: 12px; height: 12px; border-radius: 50%; }}
  </style>
</head>
<body class="p-4 sm:p-6 lg:p-8">
  <div class="max-w-7xl mx-auto flex justify-center gap-3 mb-6">
    <a href="dashboard.html" class="px-5 py-2 rounded-full font-bold text-sm bg-[#0071e3] text-white shadow-md shadow-[#0071e3]/30 flex items-center gap-2">🇺🇸 ตลาดหุ้นอเมริกา (S&amp;P 500)</a>
    <a href="dashboard_thai.html" class="px-5 py-2 rounded-full font-bold text-sm bg-white/80 hover:bg-white text-slate-600 border border-slate-200/80 shadow-sm flex items-center gap-2 transition-all">🇹🇭 ตลาดหุ้นไทย (SET100)</a>
  </div>
  <div class="max-w-7xl mx-auto bg-white/75 backdrop-blur-2xl rounded-[2.5rem] p-6 sm:p-8 mb-8 border border-white/80 shadow-[0_20px_50px_rgba(0,0,0,0.06)]">
    <div class="flex items-center justify-between pb-6 mb-6 border-b border-slate-200/60">
      <div class="flex items-center gap-2.5">
        <span class="traffic-dot bg-[#ff5f56] border border-[#e0443e]"></span>
        <span class="traffic-dot bg-[#ffbd2e] border border-[#dea123]"></span>
        <span class="traffic-dot bg-[#27c93f] border border-[#1aab29]"></span>
        <span class="ml-3 text-xs font-semibold tracking-wide text-slate-400 uppercase">S&amp;P 500 Terminal</span>
      </div>
      <div class="text-xs sm:text-sm font-medium text-slate-500">🕒 {timestamp_str}</div>
    </div>
    <div class="flex flex-col md:flex-row items-start md:items-center justify-between gap-6">
      <div>
        <h1 class="text-3xl sm:text-4xl lg:text-5xl font-extrabold tracking-tight text-[#1d1d1f]">S&amp;P 500 Radar Terminal</h1>
        <p class="text-base sm:text-lg font-medium text-slate-500">คัดกรองหุ้นอเมริกาชั้นนำ ย่อตัวลึก + SMC Sweep + แท่งกลับตัว + วิเคราะห์ตามสัญญาณ</p>
      </div>
      <div class="bg-white/90 backdrop-blur-xl px-5 py-3.5 rounded-2xl border border-white/80 shadow-sm flex items-center gap-4">
        <div class="w-3.5 h-3.5 rounded-full {regime_color} shadow-sm animate-pulse"></div>
        <div>
          <div class="text-xs font-semibold text-slate-400 uppercase tracking-wider">S&amp;P 500</div>
          <div class="text-base sm:text-lg font-bold text-slate-800">{regime_text}</div>
        </div>
      </div>
    </div>
    <div class="grid grid-cols-1 sm:grid-cols-3 gap-4 mt-6 pt-6 border-t border-slate-200/60">
      <div class="bg-white/60 backdrop-blur-lg rounded-2xl p-4 sm:p-5 border border-white/80 shadow-sm">
        <div class="text-sm font-semibold text-slate-500">หุ้นเกรด A+</div>
        <div class="text-4xl font-extrabold text-[#1d1d1f] mt-1">{len(grade_a)} <span class="text-sm font-semibold text-[#0071e3]">ตัว</span></div>
        <div class="text-xs sm:text-sm text-slate-400 font-medium mt-0.5">ผ่านเกณฑ์ครบ: {count_top} ตัว</div>
      </div>
      <div class="bg-white/60 backdrop-blur-lg rounded-2xl p-4 sm:p-5 border border-white/80 shadow-sm">
        <div class="text-sm font-semibold text-slate-500">Watchlist</div>
        <div class="text-4xl font-extrabold text-[#1d1d1f] mt-1">{len(watchlist)} <span class="text-sm font-semibold text-amber-600">ตัว</span></div>
        <div class="text-xs sm:text-sm text-slate-400 font-medium mt-0.5">ย่อตัวลึก รอสัญญาณ</div>
      </div>
      <div class="bg-white/60 backdrop-blur-lg rounded-2xl p-4 sm:p-5 border border-white/80 shadow-sm">
        <div class="text-sm font-semibold text-slate-500">S&amp;P 500</div>
        <div class="text-4xl font-extrabold text-[#1d1d1f] mt-1">{spx_close:.2f} <span class="text-sm font-semibold text-emerald-600">จุด</span></div>
        <div class="text-xs sm:text-sm text-slate-400 font-medium mt-0.5">EMA200: {spx_ema:.2f}</div>
      </div>
    </div>
  </div>
  <main class="max-w-7xl mx-auto">
    <div id="cardsGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      {cards_html if grade_a else empty_html}
    </div>
    <div class="mt-12 mb-8">
      <div class="flex items-center justify-between mb-4">
        <h2 class="text-2xl sm:text-3xl font-extrabold text-slate-900 tracking-tight">👀 Watchlist หุ้นคุณภาพในโซนถูก</h2>
        <span class="px-3.5 py-1 rounded-full text-sm font-bold bg-amber-500/15 text-amber-900 border border-amber-300">{len(watchlist)} ตัว</span>
      </div>
      <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">{watchlist_html}</div>
    </div>
  </main>
  <footer class="max-w-7xl mx-auto text-center py-10 text-xs sm:text-sm text-slate-400 font-medium">
    Automated S&amp;P 500 Scanner • Rule-based Technical Analysis
  </footer>
</body>
</html>"""
    with open(DASHBOARD_FILE, "w", encoding="utf-8") as f:
        f.write(full_html)
    print(f"✅ Dashboard saved: {DASHBOARD_FILE}")


# =========================================================
# MAIN SCANNER LOGIC
# =========================================================
def main():
    print("=====================================================")
    print("🚀 เริ่มสแกนตลาดหุ้นอเมริกา (S&P 500)...")
    print(f"🕒 เวลา: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=====================================================")

    regime, spx_close, spx_ema, pct_diff = check_sp500_regime()
    print(f"📊 สภาวะ S&P 500: {regime} (SPX: {spx_close:.2f} / EMA200: {spx_ema:.2f})")

    grade_a = []
    watchlist = []

    min_score = regime_min_score(regime, base_score=MIN_SCORE_BASE, mode=REGIME_FILTER_MODE)
    if min_score >= 90:
        print(f"⚠️ S&P 500 เป็น {regime} -> ระงับการแจ้งเตือนทั้งหมดวันนี้")
    elif min_score != MIN_SCORE_BASE:
        print(f"⚠️ S&P 500 เป็น {regime} -> ยกระดับเกณฑ์เป็น {min_score}/3")
    else:
        print(f"ℹ️ เกณฑ์แจ้งเตือนขั้นต่ำ: {min_score}/4 สัญญาณ")

    warned_bar = False
    for sym in UNIVERSE_US:
        try:
            t = yf.Ticker(sym)
            df = t.history(period="1y")
            df, note = drop_incomplete_last_bar(df, "US")
            if note and not warned_bar:
                print(f"ℹ️ {note}")
                warned_bar = True
            if df.empty or len(df) < 30:
                continue

            latest_close = df['Close'].iloc[-1]
            df['52W_High'] = rolling_high(df, window=250, min_periods=30)
            high_52w = df['52W_High'].iloc[-1]
            drawdown = ((latest_close - high_52w) / high_52w) * 100

            df['RSI'] = calculate_rsi(df['Close'])
            latest_rsi = df['RSI'].iloc[-1]

            if (drawdown <= -10.0 and latest_rsi <= 45.0) or (drawdown <= -8.0 and latest_rsi <= 38.0):
                df['EMA9'] = df['Close'].ewm(span=9, adjust=False).mean()
                df['EMA50'] = df['Close'].ewm(span=50, adjust=False).mean()
                ema_pass = bool(latest_close > df['EMA9'].iloc[-1])

                lb = SIGNAL_LOOKBACK_DAYS
                sweep_pass = bool(detect_liquidity_sweep(df, lookback=10).iloc[-lb:].any())

                pa_series = detect_hammer(df, wick_mult=1.8) | detect_bullish_engulfing(df)
                pa_pass = bool(pa_series.iloc[-lb:].any())

                vol_spike = detect_volume_spike(df, window=20, threshold=2.0)
                vol_ratio = detect_volume_ratio(df, window=20)
                rsi_div = detect_rsi_bullish_divergence(df)

                score = int(sweep_pass) + int(pa_pass) + int(ema_pass) + int(vol_spike)

                stop_loss = float(df['Low'].iloc[-3:].min()) * 0.99
                take_profit = max(float(df['EMA50'].iloc[-1]), float(latest_close) * 1.08)

                news_text = fetch_us_news(sym)

                stock_data = {
                    "symbol": sym,
                    "price": latest_close,
                    "drawdown": abs(drawdown),
                    "rsi": latest_rsi,
                    "sweep": sweep_pass,
                    "pa": pa_pass,
                    "ema": ema_pass,
                    "volume_spike": vol_spike,
                    "vol_ratio": vol_ratio,
                    "rsi_divergence": rsi_div,
                    "score": score,
                    "stop_loss": stop_loss,
                    "take_profit": take_profit,
                    "sl_pct": ((stop_loss - latest_close) / latest_close) * 100,
                    "tp_pct": ((take_profit - latest_close) / latest_close) * 100,
                    "news_summary": news_text
                }

                if score >= min_score:
                    print(f"🔎 พบ {sym} (คะแนน {score}/4)")
                    stock_data["ai_verdict"] = ask_ai_us(
                        sym, latest_close, abs(drawdown), latest_rsi, news_text,
                        sweep_pass, pa_pass, ema_pass, score,
                        vol_spike, rsi_div, vol_ratio)
                    grade_a.append(stock_data)
                else:
                    stock_data["ai_verdict"] = "โซนของถูก รอยืนยันสัญญาณกลับตัว"
                    watchlist.append(stock_data)

        except Exception as e:
            print(f"Error processing {sym}: {e}")
            continue

    grade_a = sorted(grade_a, key=lambda x: (x['score'], -x['drawdown']), reverse=True)
    watchlist = sorted(watchlist, key=lambda x: (x['score'], -x['drawdown']), reverse=True)[:6]

    generate_dashboard_us_html(regime, spx_close, spx_ema, pct_diff, grade_a, watchlist)

    if grade_a:
        msg = f"🇺🇸 *แจ้งเตือนเรดาร์หุ้นอเมริกา (S&P 500) เกรด A+*\n"
        msg += f"🗓️ {datetime.now().strftime('%d/%m/%Y')} | สภาวะ SPX: *{regime}*\n"
        msg += f"------------------------------------\n"
        for s in grade_a[:4]:
            clean_name = s['symbol']
            score_text = "ผ่านครบ 4 สัญญาณ" if s['score'] >= 4 else f"ผ่าน {s['score']}/4 สัญญาณ"
            extras = []
            if s.get('volume_spike'):
                extras.append(f"🔥 Vol {s['vol_ratio']:.1f}x")
            if s.get('rsi_divergence'):
                extras.append("📈 RSI Div")
            extra_txt = " | ".join(extras)
            msg += f"🟢 *{clean_name}* (ราคา ${s['price']:.2f})\n"
            msg += f"• ย่อตัว: *-{s['drawdown']:.1f}%* | RSI: *{s['rsi']:.1f}*\n"
            msg += f"• สัญญาณ: *{score_text}*"
            if extra_txt:
                msg += f" ({extra_txt})"
            msg += "\n"
            msg += f"• 🎯 *จุดเข้า:* ${s['price']:.2f} | 🛑 *SL:* ${s['stop_loss']:.2f} ({s['sl_pct']:.1f}%)\n"
            msg += f"• 🏆 *เป้าขาย:* ${s['take_profit']:.2f} (+{s['tp_pct']:.1f}%)\n"
            msg += f"• 🧠 *วิเคราะห์สัญญาณ:* _{s['ai_verdict']}_\n\n"

        live_url = get_live_tunnel_url()
        if live_url:
            msg += f"🌐 *เปิดดู Dashboard ฉบับเต็ม:*\n{live_url}/dashboard.html\n"
        else:
            msg += "_(หา URL ของ tunnel ไม่เจอ — ตรวจสอบว่า cloudflared ทำงานอยู่หรือไม่)_\n"
        send_telegram_alert(msg)
        print(f"✅ ส่งแจ้งเตือนหุ้นอเมริกา {len(grade_a)} ตัว เข้า Telegram สำเร็จ!")
    elif min_score >= 90:
        print(f"ℹ️ S&P 500 อยู่ใต้ EMA200 (BEAR) — ระงับการแจ้งเตือนวันนี้")
    else:
        print("ℹ️ วันนี้ไม่มีหุ้นอเมริกาเข้าเกณฑ์เกรด A+")

    print(f"\n📊 สรุป: {len(grade_a)} หุ้นเกรด A+ | {len(watchlist)} หุ้น Watchlist")


if __name__ == "__main__":
    main()