#!/usr/bin/env python3
"""
Dahua Camera Settings Application Script
Applies optimal settings across all cameras in 4 phases
"""

import requests
import json
import os
import urllib3
from requests.auth import HTTPDigestAuth
from urllib3.exceptions import InsecureRequestWarning

# Suppress SSL warnings
urllib3.disable_warnings(InsecureRequestWarning)

# Credentials
AUTH = HTTPDigestAuth('admin', os.popen('cred dahua/default').read().strip())
BASE_IP = '192.168.0.{}'

# Camera groups
CAMERAS_7FPS = [210, 211, 212, 213, 215, 236, 239]  # Will be set to 15 FPS (except .215)
CAMERAS_25FPS = [201, 202, 203, 205, 206, 209]  # Will be set to 20 FPS
CAMERA_215_SPECIAL = 215  # 2MP camera with special settings
ALL_CAMERAS = list(range(201, 254))  # .201 - .253

# Motion detection cameras (subset)
MOTION_CAMERAS = [201, 202, 203, 205, 210, 211, 212, 213, 215, 236, 239]

# AI/SMD cameras
TAURUS_CAMERAS = [206, 209, 236, 239]
VOLT_CAMERAS = [202, 203]

# Results log
results = []

def log_result(ip, phase, action, status, response_text, verified=False):
    """Log a result"""
    result = {
        'ip': ip,
        'phase': phase,
        'action': action,
        'status': status,
        'response': response_text[:200] if response_text else '',  # Truncate long responses
        'verified': verified
    }
    results.append(result)
    status_str = f"✓ {status}" if status == 200 else f"✗ {status}"
    print(f"  [{status_str}] {action}")
    return result

def make_request(ip, url_path, description, phase):
    """Make HTTP request with digest auth"""
    url = f"http://{ip}/cgi-bin/{url_path}"
    try:
        response = requests.get(url, auth=AUTH, timeout=15, verify=False)
        log_result(ip, phase, description, response.status_code, response.text)
        return response.status_code == 200, response
    except requests.exceptions.Timeout:
        log_result(ip, phase, description, 0, 'TIMEOUT')
        return False, None
    except requests.exceptions.ConnectionError:
        log_result(ip, phase, description, 0, 'CONNECTION_ERROR')
        return False, None
    except Exception as e:
        log_result(ip, phase, description, 0, str(e)[:100])
        return False, None

def phase1_video_settings():
    """Phase 1: Apply FPS, Bitrate, GOP settings"""
    print("\n" + "="*60)
    print("FAZA 1: Video Settings (FPS, BitRate, GOP)")
    print("="*60)
    
    # Cameras from 7 FPS -> 15 FPS (except .215)
    print("\n--- Kamere s 7 FPS -> 15 FPS (bez .215) ---")
    for cam in CAMERAS_7FPS:
        if cam == CAMERA_215_SPECIAL:
            continue
        ip = BASE_IP.format(cam)
        print(f"\n[{ip}] Postavke 15 FPS / 4096 kbps / GOP 30:")
        url = (f"configManager.cgi?action=setConfig&"
               f"Encode[0].MainFormat[0].Video.FPS=15&"
               f"Encode[0].MainFormat[0].Video.BitRate=4096&"
               f"Encode[0].MainFormat[0].Video.GOP=30")
        make_request(ip, url, "set FPS=15 BitRate=4096 GOP=30", 1)
    
    # Camera .215 special (2MP)
    print("\n--- Kamera .215 (2MP) posebne postavke ---")
    ip = BASE_IP.format(CAMERA_215_SPECIAL)
    print(f"\n[{ip}] Postavke 20 FPS / 3072 kbps / GOP 40:")
    url = (f"configManager.cgi?action=setConfig&"
           f"Encode[0].MainFormat[0].Video.FPS=20&"
           f"Encode[0].MainFormat[0].Video.BitRate=3072&"
           f"Encode[0].MainFormat[0].Video.GOP=40")
    make_request(ip, url, "set FPS=20 BitRate=3072 GOP=40 (2MP special)", 1)
    
    # Cameras from 25 FPS -> 20 FPS
    print("\n--- Kamere s 25 FPS -> 20 FPS ---")
    for cam in CAMERAS_25FPS:
        ip = BASE_IP.format(cam)
        print(f"\n[{ip}] Postavke 20 FPS / 4096 kbps / GOP 40:")
        url = (f"configManager.cgi?action=setConfig&"
               f"Encode[0].MainFormat[0].Video.FPS=20&"
               f"Encode[0].MainFormat[0].Video.BitRate=4096&"
               f"Encode[0].MainFormat[0].Video.GOP=40")
        make_request(ip, url, "set FPS=20 BitRate=4096 GOP=40", 1)

def phase2_ntp_settings():
    """Phase 2: Apply NTP settings to all devices"""
    print("\n" + "="*60)
    print("FAZA 2: NTP Postavke (sve kamere + NVR-ovi)")
    print("="*60)
    
    for cam in ALL_CAMERAS:
        ip = BASE_IP.format(cam)
        print(f"\n[{ip}] NTP postavke:")
        url = (f"configManager.cgi?action=setConfig&"
               f"NTP.Address=zg1.ntp.carnet.hr&"
               f"NTP.Enable=true&"
               f"NTP.Port=123&"
               f"NTP.UpdatePeriod=60")
        make_request(ip, url, "set NTP=zg1.ntp.carnet.hr Enable=true Port=123 Period=60", 2)

def phase3_motion_detection():
    """Phase 3: Enable motion detection"""
    print("\n" + "="*60)
    print("FAZA 3: Motion Detection (uključivanje)")
    print("="*60)
    
    for cam in MOTION_CAMERAS:
        ip = BASE_IP.format(cam)
        print(f"\n[{ip}] Motion Detection:")
        url = (f"configManager.cgi?action=setConfig&"
               f"MotionDetect[0].Enable=true&"
               f"MotionDetect[0].Level=3")
        make_request(ip, url, "set MotionDetect Enable=true Level=3", 3)

def phase4_ai_smd():
    """Phase 4: Enable AI/SMD functions"""
    print("\n" + "="*60)
    print("FAZA 4: AI/SMD Funkcije")
    print("="*60)
    
    # Taurus cameras - SmartDetect
    print("\n--- Taurus kamere (SmartDetect) ---")
    for cam in TAURUS_CAMERAS:
        ip = BASE_IP.format(cam)
        print(f"\n[{ip}] SmartDetect:")
        url = f"configManager.cgi?action=setConfig&SmartDetect[0].Enable=true"
        success, _ = make_request(ip, url, "set SmartDetect Enable=true", 4)
        
        # If SmartDetect fails, try VideoAnalyseRule
        if not success:
            print(f"  [RETRY] VideoAnalyseRule za {ip}:")
            url = f"configManager.cgi?action=setConfig&VideoAnalyseRule[0][0].Enable=true"
            make_request(ip, url, "set VideoAnalyseRule[0][0] Enable=true", 4)
    
    # Volt cameras - SmartDetect
    print("\n--- Volt kamere (SmartDetect) ---")
    for cam in VOLT_CAMERAS:
        ip = BASE_IP.format(cam)
        print(f"\n[{ip}] SmartDetect:")
        url = f"configManager.cgi?action=setConfig&SmartDetect[0].Enable=true"
        success, _ = make_request(ip, url, "set SmartDetect Enable=true", 4)
        
        # If SmartDetect fails, try VideoAnalyseRule
        if not success:
            print(f"  [RETRY] VideoAnalyseRule za {ip}:")
            url = f"configManager.cgi?action=setConfig&VideoAnalyseRule[0][0].Enable=true"
            make_request(ip, url, "set VideoAnalyseRule[0][0] Enable=true", 4)

def verification_scan():
    """Final verification: Check all settings were applied"""
    print("\n" + "="*60)
    print("VERIFIKACIJSKI SCAN")
    print("="*60)
    
    # Get all unique camera IPs that had successful changes
    changed_ips = set()
    for r in results:
        if r['status'] == 200:
            changed_ips.add(r['ip'])
    
    print(f"\nProvjera {len(changed_ips)} uređaja s uspješnim promjenama...")
    
    verified_count = 0
    for ip in sorted(changed_ips):
        print(f"\n[{ip}] Verifikacija:")
        
        # Check Encode settings
        url = f"configManager.cgi?action=getConfig&name=Encode"
        success_encode, resp_encode = make_request(ip, url, "verify Encode settings", "verify")
        
        # Check NTP settings
        url = f"configManager.cgi?action=getConfig&name=NTP"
        success_ntp, resp_ntp = make_request(ip, url, "verify NTP settings", "verify")
        
        # Check MotionDetect settings
        url = f"configManager.cgi?action=getConfig&name=MotionDetect"
        success_motion, resp_motion = make_request(ip, url, "verify MotionDetect settings", "verify")
        
        # Mark as verified if at least encode and ntp were readable
        if success_encode and success_ntp:
            verified_count += 1
            # Update results with verified flag
            for r in results:
                if r['ip'] == ip and r['status'] == 200:
                    r['verified'] = True
    
    print(f"\n✓ Verificirano: {verified_count}/{len(changed_ips)} uređaja")
    return verified_count

def save_log():
    """Save complete log to JSON file"""
    log_path = '/home/tropic_bot/.openclaw/workspace/dahua-firmware/settings-apply-log.json'
    
    # Ensure directory exists
    os.makedirs(os.path.dirname(log_path), exist_ok=True)
    
    # Calculate summary
    successful = len([r for r in results if r['status'] == 200])
    failed = len([r for r in results if r['status'] != 200])
    verified = len([r for r in results if r['verified']])
    
    output = {
        'summary': {
            'total_commands': len(results),
            'successful': successful,
            'failed': failed,
            'verified_devices': verified
        },
        'results': results
    }
    
    with open(log_path, 'w') as f:
        json.dump(output, f, indent=2)
    
    print(f"\n✓ Log spremljen u: {log_path}")
    return log_path

def main():
    print("="*60)
    print("DAHUA KAMERE - PRIMJENA OPTIMALNIH POSTAVKI")
    print("="*60)
    print(f"Ukupno kamera za obradu: {len(set(CAMERAS_7FPS + CAMERAS_25FPS + ALL_CAMERAS))}")
    
    try:
        # Execute all phases
        phase1_video_settings()
        phase2_ntp_settings()
        phase3_motion_detection()
        phase4_ai_smd()
        
        # Verification scan
        verification_scan()
        
        # Save log
        log_path = save_log()
        
        # Print summary
        print("\n" + "="*60)
        print("SAŽETAK")
        print("="*60)
        successful = len([r for r in results if r['status'] == 200])
        failed = len([r for r in results if r['status'] != 200])
        verified = len([r for r in results if r['verified']])
        
        print(f"\nUkupno komandi: {len(results)}")
        print(f"✓ Uspješno: {successful}")
        print(f"✗ Neuspješno: {failed}")
        print(f"✓ Verificirano: {verified}")
        
        if failed > 0:
            print("\nNeuspješne komande:")
            for r in results:
                if r['status'] != 200:
                    print(f"  - {r['ip']}: {r['action']} (status: {r['status']}, response: {r['response'][:50]})")
        
        print(f"\nDetaljan log: {log_path}")
        
    except KeyboardInterrupt:
        print("\n\nPrekinuto od korisnika. Spremam log...")
        save_log()
    except Exception as e:
        print(f"\n\nGreška: {e}")
        save_log()
        raise

if __name__ == '__main__':
    main()
