#!/usr/bin/env python3
import os
import sys
import json
import subprocess
import urllib.request
import urllib.error
from datetime import datetime
from pathlib import Path

ADDON_DIR   = Path("/usr/local/mgr5/addon")
CONFIG_PATH = ADDON_DIR / "config.json"
STATE_PATH  = ADDON_DIR / "state.json"

def load_config():
    if CONFIG_PATH.exists():
        with open(CONFIG_PATH, "r", encoding="utf-8") as f:
            return json.load(f)
    return {}

def load_state():
    if STATE_PATH.exists():
        with open(STATE_PATH, "r", encoding="utf-8") as f:
            return json.load(f)
    return {}

def save_state(state):
    with open(STATE_PATH, "w", encoding="utf-8") as f:
        json.dump(state, f, indent=2)

def send_telegram(token, chat_id, text):
    if not token or not chat_id: return
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    data = json.dumps({"chat_id": chat_id, "text": text, "parse_mode": "HTML"}).encode('utf-8')
    req = urllib.request.Request(url, data=data, headers={'Content-Type': 'application/json'})
    try:
        with urllib.request.urlopen(req, timeout=10) as r: pass
    except: pass

def send_max(token, chat_id, text):
    if not token or not chat_id: return
    
    url = f"https://platform-api2.max.ru/messages?chat_id={chat_id}"
    
    clean_text = text.replace("<b>", "").replace("</b>", "").replace("<code>", "").replace("</code>", "")
    
    payload = {
        "text": clean_text
    }
    
    try:
        data = json.dumps(payload, ensure_ascii=False).encode('utf-8')
        
        req = urllib.request.Request(url, data=data, method='POST')
        
        req.add_header('Content-Type', 'application/json; charset=utf-8')
        req.add_header('Authorization', token.strip())
        req.add_header('Content-Length', str(len(data)))
        
        with urllib.request.urlopen(req, timeout=10) as r:
            pass
            
    except urllib.error.HTTPError as e:
        err_body = e.read().decode('utf-8') if e.fp else ""
        with open("/tmp/sitemonitor_max_error.log", "a") as log_file:
            log_file.write(f"[{datetime.now()}] Max HTTP {e.code}: {e.reason} | Response: {err_body}\n")
    except Exception as e:
        with open("/tmp/sitemonitor_max_error.log", "a") as log_file:
            log_file.write(f"[{datetime.now()}] Max Connection Error: {str(e)}\n")
            
def check_site(domain, timeout):
    #url = f"http://{domain}"
    try:
        puny_domain = domain.encode('idna').decode('ascii')
        url = f"http://{puny_domain}"
    except Exception:
        url = f"http://{domain}"
    start = datetime.now()
    try:
        req = urllib.request.Request(url, headers={'User-Agent': 'ispmanager-SiteMonitor/1.0'})
        with urllib.request.urlopen(req, timeout=timeout) as response:
            code = response.getcode()
            rt = int((datetime.now() - start).total_seconds() * 1000)
            if code in [200, 301, 302, 401, 403]:
                return "up", rt
            return "down", rt
    except urllib.error.HTTPError as e:
        rt = int((datetime.now() - start).total_seconds() * 1000)
        return "up" if e.code in [401, 403, 404] else "down", rt
    except:
        return "down", None

def main():
    cfg = load_config()
    state = load_state()
    monitored_sites = cfg.get("monitored_sites", [])
    if not monitored_sites:
        sys.exit(0)

    timeout = cfg.get("timeout", 10)
    
    # Конфиг Telegram
    tg_token = cfg.get("telegram_token", "")
    tg_chat = cfg.get("telegram_chat_id", "")
    notify_tg = cfg.get("notify_telegram", False)
    
    # Конфиг Max
    max_token = cfg.get("max_token", "")
    max_chat = cfg.get("max_chat_id", "")
    notify_max = cfg.get("notify_max", False)

    for domain in monitored_sites:
        current_status, rt = check_site(domain, timeout)
        old_state = state.get(domain, {})
        old_status = old_state.get("status", "unknown")
        
        state[domain] = {
            "status": current_status,
            "response_time": rt,
            "checked_at": datetime.now().isoformat()
        }

        if old_status != "unknown" and old_status != current_status:
            if current_status == "down":
                msg = f"🔴 CRITICAL: Site {domain} is UNAVAILABLE!"
            else:
                msg = f"🟢 RECOVERY: Site {domain} is back online ({rt} ms)."
            
            if notify_tg:
                send_telegram(tg_token, tg_chat, msg)
                
            if notify_max:
                send_max(max_token, max_chat, msg)

    save_state(state)

if __name__ == "__main__":
    main()