#!/usr/bin/python3

#
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-2.0-only
#

# Import the network configuration exported by the master node but in a disabled state

import os
import sys
import json
import subprocess
from euci import EUci
from nethsec import utils

out_dir = "/etc/ha"

def import_interfaces(file):
    u = EUci()
    if not os.path.exists(os.path.join(out_dir, file)):
        return
    with open(os.path.join(out_dir, file), 'r') as f:
        interfaces = json.load(f)
    for interface, options in interfaces.items():
        u.set('network', interface, 'interface')
        u.set('network', interface, 'ns_tag', ['ha'])
        u.set('network', interface, 'auto', '0')
        for opt in options:
            u.set('network', interface, opt, options[opt])
    u.commit('network')

def import_wireguard_peers():
    u = EUci()
    if not os.path.exists(os.path.join(out_dir, 'wg_peers')):
        return
    with open(os.path.join(out_dir, 'wg_peers'), 'r') as f:
        peers = json.load(f)
    for section, options in peers.items():
        stype = "wireguard_"+section.split("_")[0]
        u.set('network', section, stype)
        u.set('network', section, 'ns_tag', ['ha'])
        for opt in options:
            u.set('network', section, opt, options[opt])
    u.commit('network')

def import_routes():
    u = EUci()
    if not os.path.exists(os.path.join(out_dir, 'routes')):
        return
    with open(os.path.join(out_dir, 'routes'), 'r') as f:
        routes = json.load(f)
    for section, options in routes.items():
        u.set('network', section, 'route')
        u.set('network', section, 'ns_tag', ['ha'])
        for opt in options:
            u.set('network', section, opt, options[opt])
    u.commit('network')

def import_hotspot_mac():
    u = EUci()
    if not os.path.exists(os.path.join(out_dir, 'hotspot')):
        return
    with open(os.path.join(out_dir, 'hotspot'), 'r') as f:
        config = json.load(f)
    target_device = ""
    if config.get('device') is not None and config.get('mac_address') is not None:
        devices = utils.get_all_by_type(u, 'network', 'device')
        for d in devices:
            device = devices[d]
            if '.' in config.get('device'):
                # Handle VLAN device, the mac address is set on the parent device
                device_name = config.get('device').split('.')[0]
            else:
                device_name = config.get('device')
            if device.get('name') == device_name:
                target_device = d
                break

    if not target_device:
        # Create a new device with the mac address
        id = utils.get_random_id()
        u.set('network', id, 'device')
        u.set('network', id, 'name', device_name)
        target_device = id

    # Set the mac address on the device
    u.set('network', target_device, 'ns_macaddr', config.get('mac_address'))
    u.set('network', target_device, 'ns_tag', ['ha'])
    u.commit('network')

def disable_dhcp_force_option():
    # Workaround: disable force option to prevent conflicts with active DHCP server
    u = EUci()
    for server in utils.get_all_by_type(u, 'dhcp', 'dhcp'):
        if u.get('dhcp', server, 'dhcpv4', default=None) == 'server':
            if u.get('dhcp', server, 'force', default="0") != "0":
                u.set('dhcp', server, 'force', '0')
                u.commit('dhcp')

def cleanup_import():
    # Make sure to cleanup all supported configurations to avoid dangling configurations
    u = EUci()
    for section in u.get_all('network'):
        tags = u.get('network', section, 'ns_tag', default=[])
        if 'ha' in tags:
            if u.get('network', section) == 'device':
                # hotspot device, cleanup mac address
                try:
                    u.delete('network', section, 'ns_macaddr')
                except:
                    pass
            else:
                u.delete('network', section)
    u.commit('network')

def import_wan_devices():
    u = EUci()
    if not os.path.exists(os.path.join(out_dir, 'wan_devices')):
        return
    with open(os.path.join(out_dir, 'wan_devices'), 'r') as f:
        devices = json.load(f)
    for device in devices:
        dtype = device.get('type', 'device')
        key = device.get('key', None)
        if not key:
            continue
        u.set('network', key, dtype)
        u.set('network', key, 'ns_tag', ['ha'])
        for opt in device:
            if opt in ['type', 'key']:
                continue
            u.set('network', key, opt, device[opt])
    u.commit('network')

if __name__ == "__main__":
    proc = subprocess.run(["/usr/libexec/rpcd/ns.ha", "call", "status"], capture_output=True, text=True)
    status = json.loads(proc.stdout)
    if status.get("role") != "backup":
        # Execute only on backup node
        sys.exit(0)
    cleanup_import()
    import_wan_devices()
    import_interfaces('wan_interfaces')
    import_interfaces('wg_interfaces')
    import_wireguard_peers()
    import_interfaces('ipsec_interfaces')
    import_interfaces('tun_interfaces')
    import_routes()
    import_hotspot_mac()
    disable_dhcp_force_option()
