#!/usr/bin/env python3
"""
Dahua Device Scanner
Skenira IP raspon 192.168.0.201-253 i prikuplja informacije o Dahua uređajima.
"""

import requests
import json
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed
from requests.auth import HTTPDigestAuth

# Konfiguracija
AUTH = HTTPDigestAuth("admin", os.popen("cred dahua/default").read().strip())
TIMEOUT = 5
BASE_IP = "192.168.0.{ip}"
IP_RANGE = range(201, 254)
OUTPUT_FILE = "/home/tropic_bot/.openclaw/workspace/dahua-firmware/device-inventory.json"

# Endpoints
ENDPOINTS = {
    "model": "/cgi-bin/magicBox.cgi?action=getDeviceType",
    "firmware": "/cgi-bin/magicBox.cgi?action=getSoftwareVersion",
    "hardware": "/cgi-bin/magicBox.cgi?action=getHardwareVersion",
    "serial": "/cgi-bin/magicBox.cgi?action=getSerialNo",
    "system_info": "/cgi-bin/magicBox.cgi?action=getSystemInfo",
}

def parse_response(text):
    """Parsira Dahua CGI response format: key=value\nkey2=value2"""
    result = {}
    for line in text.strip().split("\n"):
        if "=" in line:
            key, value = line.split("=", 1)
            result[key.strip()] = value.strip()
    return result

def check_device(ip):
    """Provjeri postoji li Dahua uređaj na IP adresi i prikupi podatke."""
    base_url = f"http://{ip}"
    device_data = {"ip": ip}
    
    try:
        # Prvo provjeri dostupnost uređaja (getDeviceType)
        response = requests.get(
            f"{base_url}{ENDPOINTS['model']}",
            auth=AUTH,
            timeout=TIMEOUT
        )
        
        if response.status_code != 200:
            return None
        
        # Parse model
        model_data = parse_response(response.text)
        device_data["model"] = model_data.get("type", "Unknown")
        
        # Dohvati firmware verziju
        try:
            resp = requests.get(
                f"{base_url}{ENDPOINTS['firmware']}",
                auth=AUTH,
                timeout=TIMEOUT
            )
            if resp.status_code == 200:
                fw_data = parse_response(resp.text)
                device_data["firmware"] = fw_data.get("version", "Unknown")
            else:
                device_data["firmware"] = "N/A"
        except Exception:
            device_data["firmware"] = "Error"
        
        # Dohvati hardware verziju
        try:
            resp = requests.get(
                f"{base_url}{ENDPOINTS['hardware']}",
                auth=AUTH,
                timeout=TIMEOUT
            )
            if resp.status_code == 200:
                hw_data = parse_response(resp.text)
                device_data["hardware"] = hw_data.get("version", "Unknown")
            else:
                device_data["hardware"] = "N/A"
        except Exception:
            device_data["hardware"] = "Error"
        
        # Dohvati serial number
        try:
            resp = requests.get(
                f"{base_url}{ENDPOINTS['serial']}",
                auth=AUTH,
                timeout=TIMEOUT
            )
            if resp.status_code == 200:
                sn_data = parse_response(resp.text)
                device_data["serial"] = sn_data.get("sn", sn_data.get("serialNumber", "Unknown"))
            else:
                device_data["serial"] = "N/A"
        except Exception:
            device_data["serial"] = "Error"
        
        # Dohvati system info (processor, uptime, chipset)
        try:
            resp = requests.get(
                f"{base_url}{ENDPOINTS['system_info']}",
                auth=AUTH,
                timeout=TIMEOUT
            )
            if resp.status_code == 200:
                sys_data = parse_response(resp.text)
                # Processor/chipset info
                device_data["platform"] = sys_data.get("processor", sys_data.get("Processor", "N/A"))
                # Uptime - pokušaj različitih varijanti
                uptime_val = sys_data.get("upTime", sys_data.get("uptime", sys_data.get("UpTime", sys_data.get("Up_Time", sys_data.get("runTime", "N/A")))))
                device_data["uptime"] = uptime_val if uptime_val else "N/A"
            else:
                device_data["platform"] = "N/A"
                device_data["uptime"] = "N/A"
        except Exception:
            device_data["platform"] = "Error"
            device_data["uptime"] = "Error"
        
        return device_data
        
    except requests.exceptions.ConnectTimeout:
        return None
    except requests.exceptions.ConnectionError:
        return None
    except requests.exceptions.ReadTimeout:
        return None
    except Exception as e:
        print(f"Error checking {ip}: {e}")
        return None

def main():
    devices = []
    ip_list = [BASE_IP.format(ip=i) for i in IP_RANGE]
    
    print(f"Skeniram {len(ip_list)} IP adresa na mreži 192.168.0.201-253...")
    print(f"Timeout: {TIMEOUT}s, Auth: digest (admin/****)")
    print("-" * 60)
    
    # Paralelno skeniranje
    with ThreadPoolExecutor(max_workers=10) as executor:
        future_to_ip = {executor.submit(check_device, ip): ip for ip in ip_list}
        
        for i, future in enumerate(as_completed(future_to_ip)):
            ip = future_to_ip[future]
            progress = (i + 1) / len(ip_list) * 100
            print(f"\rProgres: {i+1}/{len(ip_list)} ({progress:.0f}%) - Testiram: {ip}", end="", flush=True)
            
            try:
                result = future.result()
                if result:
                    devices.append(result)
                    print(f"\n[+] Pronađen: {ip} - {result.get('model', 'Unknown')}")
            except Exception as e:
                pass
    
    print(f"\n{'-' * 60}")
    print(f"Skeniranje završeno. Pronađeno {len(devices)} uređaja.")
    
    # Sortiraj po IP adresi
    devices.sort(key=lambda x: int(x['ip'].split('.')[-1]))
    
    # Spremi u JSON
    with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
        json.dump(devices, f, indent=2, ensure_ascii=False)
    
    print(f"Rezultati spremljeni u: {OUTPUT_FILE}")
    
    # Ispiši sažetak
    if devices:
        print("\n=== PRONAĐENI UREĐAJI ===")
        for d in devices:
            print(f"\nIP: {d['ip']}")
            print(f"  Model:     {d.get('model', 'N/A')}")
            print(f"  Firmware:  {d.get('firmware', 'N/A')}")
            print(f"  Hardware:  {d.get('hardware', 'N/A')}")
            print(f"  Serial:    {d.get('serial', 'N/A')}")
            print(f"  Platform:  {d.get('platform', 'N/A')}")
            print(f"  Uptime:    {d.get('uptime', 'N/A')}")
    
    return devices

if __name__ == "__main__":
    main()
