#!/usr/bin/env python3
"""UptimeRobot check + alert - Mavis 21/07/2026.
Ogni 5 min interroga UptimeRobot API e manda alert email se VPS down.
"""
import os
import sys
import time
import json
import logging
import requests
from pathlib import Path
from datetime import datetime, timezone

LOG_FILE = '/opt/charter-live/logs/uptime_check.log'
ENV_FILE = Path('/opt/charter-live/.env.uptimerobot')
ALERT_ENV_FILE = Path('/opt/charter-live/.env.alerts')

logging.basicConfig(
    filename=LOG_FILE,
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s'
)
log = logging.getLogger()

POLL_SECONDS = 300  # 5 minuti


def load_env(path):
    cfg = {}
    if not path.exists():
        return cfg
    with open(path) as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith('#') or '=' not in line:
                continue
            k, v = line.split('=', 1)
            cfg[k.strip()] = v.strip()
    return cfg


def get_monitors(api_key):
    """Chiama UptimeRobot API per ottenere lo stato dei monitor."""
    try:
        r = requests.post(
            'https://api.uptimerobot.com/v2/getMonitors',
            data={'api_key': api_key, 'format': 'json', 'logs': 1},
            timeout=10
        )
        data = r.json()
        if data.get('stat') != 'ok':
            log.error(f'UptimeRobot API error: {data.get("message", "?")}')
            return None
        return data.get('monitors', [])
    except Exception as e:
        log.error(f'UptimeRobot API exception: {e}')
        return None


def send_email_alert(subject, body):
    """Manda email di alert se SMTP e\u0026 credenziali configurati."""
    cfg = load_env(ALERT_ENV_FILE)
    if not cfg or 'SMTP_HOST' not in cfg:
        return False
    try:
        import smtplib
        from email.mime.text import MIMEText
        from email.mime.multipart import MIMEMultipart
        msg = MIMEMultipart()
        msg['From'] = cfg['SMTP_USER']
        msg['To'] = cfg['ALERT_EMAIL_TO']
        msg['Subject'] = f'[Charter VPS] [UPTIME] {subject}'
        msg.attach(MIMEText(body, 'plain'))
        with smtplib.SMTP(cfg['SMTP_HOST'], int(cfg.get('SMTP_PORT', '587'))) as server:
            server.starttls()
            server.login(cfg['SMTP_USER'], cfg['SMTP_PASS'])
            server.send_message(msg)
        return True
    except Exception as e:
        log.error(f'Email alert error: {e}')
        return False


def main_loop():
    log.info('=== UPTIME CHECK STARTED ===')
    cfg = load_env(ENV_FILE)
    api_key = cfg.get('UPTIMEROBOT_API_KEY')
    if not api_key:
        log.error('UPTIMEROBOT_API_KEY mancante in .env.uptimerobot')
        sys.exit(1)

    last_state = {}  # {monitor_id: status_int}

    while True:
        try:
            monitors = get_monitors(api_key)
            if monitors is None:
                log.warning('UptimeRobot non raggiungibile, riprovo al prossimo ciclo')
            else:
                for m in monitors:
                    mid = m.get('id')
                    name = m.get('friendly_name', '?')
                    url = m.get('url', '?')
                    status = m.get('status', 0)  # 0=paused, 1=not checked, 2=up, 9=down
                    prev = last_state.get(mid, -1)
                    if status == 9 and prev != 9:
                        # DOWN!
                        msg = f'VPS DOWN: {name} ({url}) - UptimeRobot status=9'
                        log.critical(msg)
                        send_email_alert('VPS DOWN', msg + chr(10) + f'Time: {datetime.now(timezone.utc).isoformat()}')
                    elif status == 2 and prev == 9:
                        # RECOVERED
                        msg = f'VPS RECOVERED: {name} ({url}) - UptimeRobot status=2'
                        log.info(msg)
                        send_email_alert('VPS Recovered', msg)
                    elif status == 9:
                        # STILL DOWN (throttle, no spam)
                        log.warning(f'VPS ancora DOWN: {name}')
                    else:
                        log.info(f'{name} ({url}): status={status} (0=paused,1=pending,2=up,9=down)')
                    last_state[mid] = status
        except Exception as e:
            log.error(f'loop error: {e}')

        time.sleep(POLL_SECONDS)


if __name__ == '__main__':
    main_loop()
