"""
Personal arb scanner - polls enabled bookmakers, detects arbs, emails you.

Two ways to run this:

1. Continuously (VPS/your own server with systemd, or just leaving a
   terminal open):
       python main.py --loop
   Runs forever, polling every POLL_INTERVAL_SECONDS. Ctrl+C to stop.

2. Once per invocation (cPanel / any host where you use cron instead of a
   background process):
       python main.py
   Runs a single scan cycle and exits. Point a cron job at this, e.g. every
   1-5 minutes, and each run is an independent scan (see README for the
   cron setup).

Note: `already_alerted` (dedup so you don't get the same arb emailed twice)
only works WITHIN one run. In --loop mode that's fine since the process
stays alive. In cron mode, each invocation starts fresh, so a persistent
arb that's still open will re-email you every cron run - this is often
useful for cron mode anyway, since arb windows are short-lived and a repeat
email means it's still live. Adjust min-profit threshold if that gets noisy.
"""

import sys
import time
import logging

import config
from scrapers.sportpesa import SportPesaScraper
from scrapers.betika import BetikaScraper
from matcher import group_by_event
from arb import detect_arb, stake_amounts
from alert import format_arb_email, send_email_alert

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler(config.LOG_FILE),
        logging.StreamHandler(),
    ],
)
logger = logging.getLogger(__name__)

ALL_SCRAPERS = {
    "sportpesa": SportPesaScraper(),
    "betika": BetikaScraper(),
}

# tracks events we've already alerted on this run, so we don't spam the same arb every 45s
already_alerted = set()


def run_once(total_stake: float = 1000.0):
    active_scrapers = [ALL_SCRAPERS[name] for name in config.ENABLED_BOOKS if name in ALL_SCRAPERS]

    all_entries = []
    for scraper in active_scrapers:
        for sport in config.SPORTS_TO_TRACK:
            try:
                entries = scraper.fetch_odds(sport)
                logger.info(f"{scraper.name}: fetched {len(entries)} odds entries for {sport}")
                all_entries.extend(entries)
            except Exception as e:
                logger.error(f"{scraper.name}: failed to fetch odds - {e}")

    events = group_by_event(all_entries)
    logger.info(f"Grouped into {len(events)} distinct events")

    for (home, away), entries in events.items():
        opportunity = detect_arb(entries, min_profit_percent=config.MIN_PROFIT_MARGIN_PERCENT)
        if opportunity is None:
            continue

        event_key = (home, away, opportunity.market)
        if event_key in already_alerted:
            continue  # already told you about this one

        legs_with_amounts = stake_amounts(opportunity, total_stake)
        body = format_arb_email(opportunity, total_stake, legs_with_amounts)
        subject = f"Arb found: {opportunity.home_team} vs {opportunity.away_team} ({opportunity.profit_margin_percent}%)"

        send_email_alert(subject, body)
        already_alerted.add(event_key)
        logger.info(f"ARB: {subject}")


def main():
    loop_mode = "--loop" in sys.argv

    logger.info("Starting arb scanner...")
    logger.info(f"Enabled books: {config.ENABLED_BOOKS}")
    logger.info(f"Min profit margin: {config.MIN_PROFIT_MARGIN_PERCENT}%")
    logger.info(f"Mode: {'continuous loop' if loop_mode else 'single run (cron-friendly)'}")

    if not loop_mode:
        # cron mode: one scan, then exit
        try:
            run_once()
        except Exception as e:
            logger.error(f"Unexpected error during scan: {e}")
        return

    # loop mode: keep running, e.g. on a VPS/systemd
    while True:
        try:
            run_once()
        except Exception as e:
            logger.error(f"Unexpected error in scan loop: {e}")
        time.sleep(config.POLL_INTERVAL_SECONDS)


if __name__ == "__main__":
    main()
