#!/usr/bin/env python3
"""Stock price monitor for TSLA and SPCX.

Alerts when prices cross configured thresholds.
Uses Yahoo Finance API (no external dependencies beyond stdlib).
Sends email via Apple iCloud SMTP.

Alert logic:
- When price DROPS BELOW a threshold: alert "Below $X"
- When price RISES ABOVE a threshold: alert "Above $X"

State is tracked in a JSON file to avoid duplicate alerts.
"""

import json
import os
import smtplib
import sys
import urllib.request
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from pathlib import Path

# ── Config ──────────────────────────────────────────────────────────
THRESHOLDS = [50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300]
TICKERS = {
    "TSLA": {"name": "Tesla", "thresholds": THRESHOLDS},
    "SPCX": {"name": "SpaceX", "thresholds": THRESHOLDS},
}

STATE_FILE = Path("/home/thesage/.hermes/scripts/stock_monitor_state.json")

APPLE_EMAIL = os.environ.get("APPLE_EMAIL", "").strip()
APPLE_APP_PASSWORD = os.environ.get("APPLE_APP_PASSWORD", "").strip()
RECIPIENT = os.environ.get("RECIPIENT", "sage.stockmans@pm.me").strip()
SMTP_HOST = "smtp.mail.me.com"
SMTP_PORT = 587

YAHOO_HEADERS = {"User-Agent": "Mozilla/5.0"}


# ── Helpers ─────────────────────────────────────────────────────────
def fetch_price(ticker: str) -> float | None:
    url = f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}"
    req = urllib.request.Request(url, headers=YAHOO_HEADERS)
    try:
        with urllib.request.urlopen(req, timeout=15) as resp:
            data = json.loads(resp.read().decode())
            result = data.get("chart", {}).get("result", [{}])[0]
            price = result.get("meta", {}).get("regularMarketPrice")
            if price is None:
                # Fallback to last close
                price = result.get("meta", {}).get("previousClose")
            return float(price) if price else None
    except Exception as e:
        print(f"Error fetching {ticker}: {e}", file=sys.stderr)
        return None


def load_state() -> dict:
    if STATE_FILE.exists():
        try:
            return json.loads(STATE_FILE.read_text())
        except json.JSONDecodeError:
            pass
    return {}


def save_state(state: dict) -> None:
    STATE_FILE.write_text(json.dumps(state, indent=2))


def send_email(subject: str, body: str) -> None:
    if not APPLE_EMAIL or not APPLE_APP_PASSWORD:
        print("Email credentials not configured.", file=sys.stderr)
        sys.exit(1)

    msg = MIMEMultipart()
    msg["From"] = APPLE_EMAIL
    msg["To"] = RECIPIENT
    msg["Subject"] = subject
    msg.attach(MIMEText(body, "plain", "utf-8"))

    with smtplib.SMTP(SMTP_HOST, SMTP_PORT) as server:
        server.starttls()
        server.login(APPLE_EMAIL, APPLE_APP_PASSWORD)
        server.sendmail(APPLE_EMAIL, RECIPIENT, msg.as_string())
    print(f"Sent: {subject}")


# ── Main ────────────────────────────────────────────────────────────
def main():
    state = load_state()
    alerts_triggered = []

    for ticker, info in TICKERS.items():
        price = fetch_price(ticker)
        if price is None:
            continue

        ticker_state = state.get(ticker, {})
        last_price = ticker_state.get("last_price")
        triggered_below = set(ticker_state.get("triggered_below", []))
        triggered_above = set(ticker_state.get("triggered_above", []))

        for threshold in info["thresholds"]:
            thresh_str = str(threshold)

            # Price dropped BELOW threshold
            if last_price is not None and last_price >= threshold and price < threshold:
                if thresh_str not in triggered_below:
                    alerts_triggered.append(
                        f"📉 {info['name']} ({ticker}) dropped BELOW ${threshold}\n"
                        f"   Current price: ${price:.2f}\n"
                        f"   Previous: ${last_price:.2f}\n"
                    )
                    triggered_below.add(thresh_str)

            # Price rose ABOVE threshold
            if last_price is not None and last_price <= threshold and price > threshold:
                if thresh_str not in triggered_above:
                    alerts_triggered.append(
                        f"📈 {info['name']} ({ticker}) rose ABOVE ${threshold}\n"
                        f"   Current price: ${price:.2f}\n"
                        f"   Previous: ${last_price:.2f}\n"
                    )
                    triggered_above.add(thresh_str)

        # Update state
        ticker_state["last_price"] = price
        ticker_state["triggered_below"] = sorted([int(x) for x in triggered_below])
        ticker_state["triggered_above"] = sorted([int(x) for x in triggered_above])
        state[ticker] = ticker_state

        print(f"{ticker}: ${price:.2f}")

    save_state(state)

    if alerts_triggered:
        body = "Stock Price Alert\n================\n\n"
        body += "\n".join(alerts_triggered)
        body += "\n\nThis is an automated alert from your stock monitor.\n"
        send_email("🚨 Stock Price Alert", body)
    else:
        print("No alerts triggered.")


if __name__ == "__main__":
    main()
