use crate::HAProxy;
use crate::{data::dhcpd::DhcpInterface, xml_utils::to_xml_str};
use log::error;
use uuid::Uuid;
use yaserde::{MaybeString, NamedList, RawXml};
use yaserde_derive::{YaDeserialize, YaSerialize};

use super::{Interface, Pischem};

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
#[yaserde(rename = "opnsense")]
pub struct OPNsense {
    pub theme: String,
    pub sysctl: Sysctl,
    pub system: System,
    pub interfaces: NamedList<Interface>,
    pub dhcpd: NamedList<DhcpInterface>,
    pub snmpd: Snmpd,
    pub syslog: Syslog,
    pub nat: Nat,
    pub filter: Filters,
    pub load_balancer: Option<LoadBalancer>,
    pub rrd: Option<RawXml>,
    pub ntpd: Ntpd,
    pub widgets: Widgets,
    pub revision: Revision,
    #[yaserde(rename = "OPNsense")]
    pub opnsense: OPNsenseXmlSection,
    pub staticroutes: StaticRoutes,
    pub ca: MaybeString,
    pub gateways: Option<RawXml>,
    pub cert: Vec<Cert>,
    pub dhcpdv6: DhcpDv6,
    pub virtualip: VirtualIp,
    pub openvpn: OpenVpn,
    pub ppps: Ppps,
    pub dyndnses: Option<Dyndnses>,
    pub vlans: Vlans,
    pub bridges: Bridges,
    pub gifs: Gifs,
    pub gres: Gres,
    pub laggs: Laggs,
    pub wireless: Wireless,
    pub hasync: Hasync,
    #[yaserde(rename = "Pischem")]
    pub pischem: Option<Pischem>,
    pub ifgroups: Ifgroups,
    pub dnsmasq: Option<RawXml>,
}

impl From<String> for OPNsense {
    fn from(content: String) -> Self {
        yaserde::de::from_str(&content)
            .map_err(|e| println!("{}", e.to_string()))
            .expect("OPNSense received invalid string, should be full XML")
    }
}

impl OPNsense {
    pub fn to_xml(&self) -> String {
        to_xml_str(self)
            .map_err(|e| error!("{}", e.to_string()))
            .expect("OPNSense could not serialize to XML")
    }
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct LoadBalancer {
    pub monitor_type: Vec<MonitorType>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct MonitorType {
    pub name: String,
    #[yaserde(rename = "type")]
    pub r#type: String,
    pub descr: String,
    pub options: Option<Options>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Ntpd {
    pub prefer: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Widgets {
    pub sequence: String,
    pub column_count: i32,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Revision {
    pub username: String,
    pub time: f64,
    pub description: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Options {
    pub path: Option<MaybeString>,
    pub host: Option<MaybeString>,
    pub code: Option<MaybeString>,
    pub send: Option<MaybeString>,
    pub expect: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Filters {
    #[yaserde(rename = "rule")]
    pub rules: Vec<Rule>,
    pub bypassstaticroutes: Option<MaybeString>,
    pub scrub: Option<RawXml>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Rule {
    #[yaserde(attribute = true)]
    pub uuid: Option<String>,
    #[yaserde(rename = "associated-rule-id")]
    pub associated_rule_id: Option<MaybeString>,
    #[yaserde(rename = "type")]
    pub r#type: Option<MaybeString>,
    pub interface: String,
    pub ipprotocol: String,
    pub statetype: Option<MaybeString>,
    pub descr: Option<MaybeString>,
    pub direction: Option<MaybeString>,
    pub category: Option<MaybeString>,
    pub quick: Option<MaybeString>,
    pub protocol: Option<MaybeString>,
    pub source: Source,
    pub icmptype: Option<MaybeString>,
    pub destination: Destination,
    pub updated: Option<Updated>,
    pub created: Option<Created>,
    pub disabled: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Source {
    pub any: Option<u8>,
    pub network: Option<MaybeString>,
    pub address: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Destination {
    pub network: Option<MaybeString>,
    pub address: Option<MaybeString>,
    pub port: Option<MaybeString>,
    pub any: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Username {
    pub user: String,
    pub host: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Sysctl {
    pub item: Vec<SysctlItem>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct SysctlItem {
    pub descr: MaybeString,
    pub tunable: String,
    pub value: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct System {
    pub use_mfs_tmp: Option<MaybeString>,
    pub use_mfs_var: Option<MaybeString>,
    pub serialspeed: u32,
    pub primaryconsole: String,
    pub secondaryconsole: Option<MaybeString>,
    pub optimization: String,
    pub hostname: String,
    pub domain: String,
    pub group: Vec<Group>,
    pub user: Vec<User>,
    pub nextuid: u32,
    pub nextgid: u32,
    pub timezone: String,
    pub timeservers: String,
    pub webgui: WebGui,
    pub usevirtualterminal: u8,
    pub disablenatreflection: String,
    pub disableconsolemenu: u8,
    pub disablevlanhwfilter: u8,
    pub disablechecksumoffloading: u8,
    pub disablesegmentationoffloading: u8,
    pub disablelargereceiveoffloading: u8,
    pub ipv6allow: u8,
    pub powerd_ac_mode: String,
    pub powerd_battery_mode: String,
    pub powerd_normal_mode: String,
    pub bogons: Bogons,
    pub crypto_hardware: Option<String>,
    pub pf_share_forward: u8,
    pub lb_use_sticky: u8,
    pub kill_states: Option<u8>,
    pub ssh: Ssh,
    pub rrdbackup: Option<i8>,
    pub netflowbackup: Option<i8>,
    pub firmware: Firmware,
    pub sudo_allow_wheel: Option<u8>,
    pub sudo_allow_group: Option<String>,
    pub enablenatreflectionhelper: Option<String>,
    pub rulesetoptimization: Option<String>,
    pub maximumstates: Option<MaybeString>,
    pub maximumfrags: Option<MaybeString>,
    pub aliasesresolveinterval: Option<MaybeString>,
    pub maximumtableentries: Option<MaybeString>,
    pub language: String,
    pub dnsserver: Option<MaybeString>,
    pub dns1gw: Option<String>,
    pub dns2gw: Option<String>,
    pub dns3gw: Option<String>,
    pub dns4gw: Option<String>,
    pub dns5gw: Option<String>,
    pub dns6gw: Option<String>,
    pub dns7gw: Option<String>,
    pub dns8gw: Option<String>,
    pub dnsallowoverride: u8,
    pub dnsallowoverride_exclude: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Ssh {
    pub group: String,
    pub noauto: u8,
    pub interfaces: MaybeString,
    pub kex: MaybeString,
    pub ciphers: MaybeString,
    pub macs: MaybeString,
    pub keys: MaybeString,
    pub enabled: String,
    pub passwordauth: u8,
    pub keysig: MaybeString,
    pub permitrootlogin: u8,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Firmware {
    #[yaserde(attribute = true)]
    pub version: String,
    pub mirror: MaybeString,
    pub flavour: MaybeString,
    pub plugins: MaybeString,
    #[yaserde(rename = "type")]
    pub firmware_type: MaybeString,
    pub subscription: MaybeString,
    pub reboot: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Bogons {
    pub interval: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Group {
    pub name: String,
    pub description: String,
    pub scope: String,
    pub gid: u32,
    pub member: Vec<u32>,
    #[yaserde(rename = "priv")]
    pub priv_field: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct User {
    pub name: String,
    pub descr: MaybeString,
    pub scope: String,
    pub groupname: Option<MaybeString>,
    pub password: String,
    pub pwd_changed_at: Option<MaybeString>,
    pub uid: u32,
    pub disabled: Option<u8>,
    pub landing_page: Option<MaybeString>,
    pub comment: Option<MaybeString>,
    pub email: Option<MaybeString>,
    pub apikeys: Option<MaybeString>,
    #[yaserde(rename = "priv")]
    pub priv_field: Option<MaybeString>,
    pub language: Option<MaybeString>,
    pub expires: Option<MaybeString>,
    pub authorizedkeys: Option<MaybeString>,
    pub dashboard: Option<MaybeString>,
    pub ipsecpsk: Option<MaybeString>,
    pub otp_seed: Option<MaybeString>,
    pub shell: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WebGui {
    pub protocol: String,
    #[yaserde(rename = "ssl-certref")]
    pub ssl_certref: String,
    pub port: MaybeString,
    #[yaserde(rename = "ssl-ciphers")]
    pub ssl_ciphers: MaybeString,
    pub interfaces: MaybeString,
    pub compression: MaybeString,
    pub nohttpreferercheck: Option<u8>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct NumberOption {
    item: MaybeString,
}

#[derive(Default, Clone, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Range {
    pub from: String,
    pub to: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct StaticMap {
    pub mac: String,
    pub ipaddr: String,
    pub hostname: String,
    pub descr: Option<MaybeString>,
    pub winsserver: MaybeString,
    pub dnsserver: MaybeString,
    pub ntpserver: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Snmpd {
    pub syslocation: MaybeString,
    pub syscontact: MaybeString,
    pub rocommunity: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Syslog {
    pub reverse: Option<MaybeString>,
    pub preservelogs: Option<MaybeString>,
    pub nologdefaultblock: Option<u8>,
    pub nologdefaultpass: Option<u8>,
    pub nologbogons: Option<u8>,
    pub nologprivatenets: Option<u8>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Nat {
    #[yaserde(rename = "outbound")]
    pub outbound: Outbound,
    #[yaserde(rename = "rule")]
    pub rules: Vec<NatRule>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Outbound {
    pub mode: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct NatRule {
    pub protocol: String,
    pub interface: String,
    pub category: MaybeString,
    pub ipprotocol: String,
    pub descr: MaybeString,
    pub tag: MaybeString,
    pub tagged: Option<MaybeString>,
    pub poolopts: PoolOpts,
    #[yaserde(rename = "associated-rule-id")]
    pub associated_rule_id: Option<MaybeString>,
    pub disabled: Option<u8>,
    pub target: String,
    #[yaserde(rename = "local-port")]
    pub local_port: i32,
    pub source: Source,
    pub destination: Destination,
    pub updated: Updated,
    pub created: Created,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct PoolOpts {
    // No specific fields for this element, can be added as needed
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Updated {
    pub username: String,
    pub time: f64,
    pub description: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Created {
    pub username: String,
    pub time: f64,
    pub description: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Filter {
    #[yaserde(attribute = true)]
    version: String,
    rules: Option<MaybeString>,
    snatrules: Option<MaybeString>,
    npt: Option<MaybeString>,
    onetoone: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
#[yaserde(rename = "OPNsense")]
pub struct OPNsenseXmlSection {
    pub captiveportal: Option<CaptivePortal>,
    pub cron: Option<Cron>,
    #[yaserde(rename = "Netflow")]
    pub netflow: Option<Netflow>,
    #[yaserde(rename = "Firewall")]
    pub firewall: Option<Firewall>,
    #[yaserde(rename = "IDS")]
    pub ids: Option<IDS>,
    #[yaserde(rename = "IPsec")]
    pub ipsec: Option<IPsec>,
    #[yaserde(rename = "Interfaces")]
    pub interfaces: Option<ConfigInterfaces>,
    #[yaserde(rename = "NodeExporter")]
    pub node_exporter: Option<RawXml>,
    #[yaserde(rename = "Kea")]
    pub kea: Option<RawXml>,
    pub monit: Option<Monit>,
    #[yaserde(rename = "OpenVPNExport")]
    pub openvpn_export: Option<OpenVPNExport>,
    pub proxy: Option<Proxy>,
    #[yaserde(rename = "Syslog")]
    pub syslog: Option<ConfigSyslog>,
    #[yaserde(rename = "TrafficShaper")]
    pub traffic_shaper: Option<RawXml>,
    pub unboundplus: Option<UnboundPlus>,
    #[yaserde(rename = "DHCRelay")]
    pub dhcrelay: Option<RawXml>,
    pub trust: Option<RawXml>,
    pub tftp: Option<Tftp>,
    #[yaserde(rename = "Nginx")]
    pub nginx: Option<RawXml>,
    pub wireguard: Option<Wireguard>,
    #[yaserde(rename = "Swanctl")]
    pub swanctl: Swanctl,
    #[yaserde(rename = "DynDNS")]
    pub dyndns: Option<DynDNS>,
    #[yaserde(rename = "OpenVPN")]
    pub openvpn: ConfigOpenVPN,
    #[yaserde(rename = "Gateways")]
    pub gateways: RawXml,
    #[yaserde(rename = "HAProxy")]
    pub haproxy: Option<HAProxy>,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Tftp {
    pub general: TftpGeneral,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct TftpGeneral {
    #[yaserde(attribute = true)]
    pub version: String,
    pub enabled: u8,
    pub listen: String,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
#[yaserde(rename = "IDS")]
pub struct IDS {
    #[yaserde(attribute = true)]
    pub version: String,
    pub rules: MaybeString,
    pub policies: MaybeString,
    #[yaserde(rename = "userDefinedRules")]
    pub user_defined_rules: MaybeString,
    pub files: MaybeString,
    #[yaserde(rename = "fileTags")]
    pub file_tags: MaybeString,
    pub general: IDSGeneral,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct IDSGeneral {
    pub enabled: Option<u8>,
    pub ips: Option<u8>,
    pub promisc: Option<u8>,
    pub interfaces: String,
    pub homenet: String,
    #[yaserde(rename = "defaultPacketSize")]
    pub default_packet_size: MaybeString,
    #[yaserde(rename = "UpdateCron")]
    pub update_cron: MaybeString,
    #[yaserde(rename = "AlertLogrotate")]
    pub alert_logrotate: String,
    #[yaserde(rename = "AlertSaveLogs")]
    pub alert_save_logs: u8,
    #[yaserde(rename = "MPMAlgo")]
    pub mpm_algo: MaybeString,
    pub detect: Detect,
    pub syslog: Option<u8>,
    pub syslog_eve: Option<u8>,
    #[yaserde(rename = "LogPayload")]
    pub log_payload: Option<u8>,
    pub verbosity: MaybeString,
    #[yaserde(rename = "eveLog")]
    pub eve_log: Option<RawXml>,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Detect {
    #[yaserde(rename = "Profile")]
    profile: MaybeString,
    toclient_groups: MaybeString,
    toserver_groups: MaybeString,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct IPsec {
    #[yaserde(attribute = true)]
    version: String,
    general: GeneralIpsec,
    #[yaserde(rename = "keyPairs")]
    key_pairs: MaybeString,
    #[yaserde(rename = "preSharedKeys")]
    pre_shared_keys: MaybeString,
    charon: Option<RawXml>,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct GeneralIpsec {
    enabled: MaybeString,
    preferred_oldsa: Option<MaybeString>,
    disablevpnrules: Option<MaybeString>,
    passthrough_networks: Option<MaybeString>,
    user_source: Option<MaybeString>,
    local_group: Option<MaybeString>,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
#[yaserde(rename = "Interfaces")]
pub struct ConfigInterfaces {
    vxlans: Vxlan,
    loopbacks: Loopback,
    neighbors: Option<Neighbors>,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Neighbors {
    #[yaserde(attribute = true)]
    version: String,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Vxlan {
    #[yaserde(attribute = true)]
    version: String,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Loopback {
    #[yaserde(attribute = true)]
    version: String,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
#[yaserde(rename = "monit")]
pub struct Monit {
    #[yaserde(attribute = true)]
    version: String,
    general: GeneralMonit,
    alert: Option<Alert>,
    service: Vec<Service>,
    test: Vec<Test>,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct GeneralMonit {
    enabled: u8,
    interval: u32,
    startdelay: u32,
    mailserver: String,
    port: u16,
    username: MaybeString,
    password: MaybeString,
    ssl: u8,
    sslversion: String,
    sslverify: u8,
    logfile: MaybeString,
    statefile: MaybeString,
    #[yaserde(rename = "eventqueuePath")]
    event_queue_path: MaybeString,
    #[yaserde(rename = "eventqueueSlots")]
    event_queue_slots: MaybeString,
    #[yaserde(rename = "httpdEnabled")]
    httpd_enabled: u8,
    #[yaserde(rename = "httpdUsername")]
    httpd_username: String,
    #[yaserde(rename = "httpdPassword")]
    httpd_password: MaybeString,
    #[yaserde(rename = "httpdPort")]
    httpd_port: u16,
    #[yaserde(rename = "httpdAllow")]
    httpd_allow: MaybeString,
    #[yaserde(rename = "mmonitUrl")]
    mmonit_url: MaybeString,
    #[yaserde(rename = "mmonitTimeout")]
    mmonit_timeout: u32,
    #[yaserde(rename = "mmonitRegisterCredentials")]
    mmonit_register_credentials: u8,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Alert {
    #[yaserde(attribute = true)]
    uuid: String,
    enabled: u8,
    recipient: String,
    noton: u8,
    events: MaybeString,
    format: MaybeString,
    reminder: MaybeString,
    description: MaybeString,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Service {
    #[yaserde(attribute = true)]
    uuid: String,
    enabled: u8,
    name: String,
    description: MaybeString,
    #[yaserde(rename = "type")]
    r#type: String,
    pidfile: MaybeString,
    #[yaserde(rename = "match")]
    r#match: MaybeString,
    path: MaybeString,
    timeout: u32,
    starttimeout: u32,
    address: MaybeString,
    interface: MaybeString,
    start: MaybeString,
    stop: MaybeString,
    tests: String,
    depends: MaybeString,
    polltime: MaybeString,
}

#[derive(Debug, YaSerialize, YaDeserialize, PartialEq)]
pub struct Test {
    #[yaserde(attribute = true)]
    uuid: String,
    name: String,
    #[yaserde(rename = "type")]
    r#type: String,
    condition: String,
    action: String,
    path: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct CaptivePortal {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "zones")]
    pub zones: Option<Zones>,
    #[yaserde(rename = "templates")]
    pub templates: Option<Templates>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Cron {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "jobs")]
    pub jobs: Option<Jobs>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Netflow {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "capture")]
    pub capture: Option<Capture>,
    #[yaserde(rename = "collect")]
    pub collect: Option<Collect>,
    #[yaserde(rename = "activeTimeout")]
    pub active_timeout: Option<u64>,
    #[yaserde(rename = "inactiveTimeout")]
    pub inactive_timeout: Option<u64>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Capture {
    #[yaserde(rename = "interfaces")]
    pub interfaces: MaybeString,
    #[yaserde(rename = "egress_only")]
    pub egress_only: MaybeString,
    #[yaserde(rename = "version")]
    pub version: MaybeString,
    #[yaserde(rename = "targets")]
    pub targets: Option<Targets>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Collect {
    #[yaserde(rename = "enable")]
    pub enable: Option<u8>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Zones {
    // Define fields for Zones, e.g.:
    #[yaserde(rename = "zone")]
    pub zones: Vec<Zone>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Zone {
    #[yaserde(attribute = true)]
    pub uuid: MaybeString,
    #[yaserde(rename = "name")]
    pub name: MaybeString,
    // Add other fields as needed
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Templates {
    // Define fields for Templates, e.g.:
    #[yaserde(rename = "template")]
    pub templates: Vec<Template>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Template {
    #[yaserde(attribute = true)]
    pub uuid: MaybeString,
    #[yaserde(rename = "name")]
    pub name: MaybeString,
    // Add other fields as needed
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Jobs {
    // Define fields for Jobs, e.g.:
    #[yaserde(rename = "job")]
    pub jobs: Vec<Job>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Job {
    #[yaserde(attribute = true)]
    pub uuid: MaybeString,
    #[yaserde(rename = "name")]
    pub name: MaybeString,
    // Add other fields as needed
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Targets {
    // Define fields for Targets, e.g.:
    #[yaserde(rename = "target")]
    pub targets: Vec<Target>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Target {
    #[yaserde(attribute = true)]
    pub uuid: MaybeString,
    #[yaserde(rename = "name")]
    pub name: MaybeString,
    // Add other fields as needed
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Firewall {
    #[yaserde(rename = "Lvtemplate")]
    pub lv_template: Option<LvTemplate>,
    #[yaserde(rename = "Category")]
    pub category: Option<Category>,
    #[yaserde(rename = "Filter")]
    pub filter: Option<Filter>,
    #[yaserde(rename = "Alias")]
    pub alias: Option<Alias>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct LvTemplate {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "templates")]
    pub templates: Option<Templates>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Category {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "categories")]
    pub categories: Option<Categories>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Categories {
    #[yaserde(rename = "category")]
    pub categories: Vec<CategoryItem>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct CategoryItem {
    #[yaserde(attribute = true)]
    pub uuid: String,
    #[yaserde(rename = "name")]
    pub name: MaybeString,
    #[yaserde(rename = "auto")]
    pub auto: Option<u8>,
    #[yaserde(rename = "color")]
    pub color: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Alias {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "geoip")]
    pub geoip: Option<GeoIP>,
    #[yaserde(rename = "aliases")]
    pub aliases: Option<Aliases>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct GeoIP {
    #[yaserde(rename = "url")]
    pub url: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Aliases {
    #[yaserde(rename = "alias")]
    pub aliases: Vec<AliasItem>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct AliasItem {
    #[yaserde(attribute = true)]
    pub uuid: String,
    pub enabled: String,
    pub name: String,
    #[yaserde(rename = "type")]
    pub r#type: String,
    pub proto: MaybeString,
    pub interface: MaybeString,
    pub counters: String,
    pub updatefreq: MaybeString,
    pub content: String,
    pub categories: MaybeString,
    pub description: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct OpenVPNExport {
    #[yaserde(attribute = true)]
    pub version: String,
    pub servers: Option<Servers>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Servers {}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
#[yaserde(rename = "proxy")]
pub struct Proxy {
    #[yaserde(attribute = true)]
    pub version: String,
    pub general: ProxyGeneral,
    pub forward: Forward,
    pub pac: Option<Pac>,
    #[yaserde(rename = "error_pages")]
    pub error_pages: ErrorPages,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct ProxyGeneral {
    pub enabled: i8,
    pub error_pages: String,
    #[yaserde(rename = "icpPort")]
    pub icp_port: MaybeString,
    pub logging: Logging,
    #[yaserde(rename = "alternateDNSservers")]
    pub alternate_dns_servers: MaybeString,
    #[yaserde(rename = "dnsV4First")]
    pub dns_v4_first: i8,
    #[yaserde(rename = "forwardedForHandling")]
    pub forwarded_for_handling: String,
    #[yaserde(rename = "uriWhitespaceHandling")]
    pub uri_whitespace_handling: String,
    #[yaserde(rename = "enablePinger")]
    pub enable_pinger: i8,
    #[yaserde(rename = "useViaHeader")]
    pub use_via_header: i8,
    #[yaserde(rename = "suppressVersion")]
    pub suppress_version: i32,
    #[yaserde(rename = "connecttimeout")]
    pub connect_timeout: MaybeString,
    #[yaserde(rename = "VisibleEmail")]
    pub visible_email: String,
    #[yaserde(rename = "VisibleHostname")]
    pub visible_hostname: MaybeString,
    pub cache: Cache,
    pub traffic: Traffic,
    #[yaserde(rename = "parentproxy")]
    pub parent_proxy: ParentProxy,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Logging {
    pub enable: Enable,
    #[yaserde(rename = "ignoreLogACL")]
    pub ignore_log_acl: MaybeString,
    pub target: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Enable {
    #[yaserde(rename = "accessLog")]
    pub access_log: i8,
    #[yaserde(rename = "storeLog")]
    pub store_log: i8,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Cache {
    pub local: LocalCache,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct LocalCache {
    pub enabled: i8,
    pub directory: String,
    pub cache_mem: i32,
    pub maximum_object_size: MaybeString,
    pub maximum_object_size_in_memory: MaybeString,
    pub memory_cache_mode: String,
    pub size: i32,
    pub l1: i32,
    pub l2: i32,
    pub cache_linux_packages: i32,
    pub cache_windows_updates: i32,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Traffic {
    pub enabled: i32,
    #[yaserde(rename = "maxDownloadSize")]
    pub max_download_size: i32,
    #[yaserde(rename = "maxUploadSize")]
    pub max_upload_size: i32,
    #[yaserde(rename = "OverallBandwidthTrotteling")]
    pub overall_bandwidth_trotteling: i32,
    #[yaserde(rename = "perHostTrotteling")]
    pub per_host_trotteling: i32,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct ParentProxy {
    pub enabled: i32,
    pub host: MaybeString,
    pub enableauth: i32,
    pub user: MaybeString,
    pub password: MaybeString,
    pub port: MaybeString,
    pub localdomains: MaybeString,
    pub localips: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Forward {
    pub interfaces: String,
    pub port: i32,
    pub sslbumpport: i32,
    pub sslbump: i32,
    pub sslurlonly: i32,
    pub sslcertificate: MaybeString,
    pub sslnobumpsites: MaybeString,
    pub ssl_crtd_storage_max_size: i32,
    pub sslcrtd_children: i32,
    pub snmp_enable: i32,
    pub snmp_port: i32,
    pub snmp_password: String,
    #[yaserde(rename = "ftpInterfaces")]
    pub ftp_interfaces: MaybeString,
    #[yaserde(rename = "ftpPort")]
    pub ftp_port: i32,
    #[yaserde(rename = "ftpTransparentMode")]
    pub ftp_transparent_mode: i32,
    #[yaserde(rename = "addACLforInterfaceSubnets")]
    pub add_acl_for_interface_subnets: i32,
    #[yaserde(rename = "transparentMode")]
    pub transparent_mode: i32,
    pub acl: Acl,
    pub icap: Icap,
    pub authentication: Authentication,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Acl {
    #[yaserde(rename = "allowedSubnets")]
    pub allowed_subnets: MaybeString,
    pub unrestricted: MaybeString,
    #[yaserde(rename = "bannedHosts")]
    pub banned_hosts: MaybeString,
    #[yaserde(rename = "whiteList")]
    pub white_list: MaybeString,
    #[yaserde(rename = "blackList")]
    pub black_list: MaybeString,
    pub browser: MaybeString,
    #[yaserde(rename = "mimeType")]
    pub mime_type: MaybeString,
    #[yaserde(rename = "googleapps")]
    pub google_apps: MaybeString,
    pub youtube: MaybeString,
    #[yaserde(rename = "safePorts")]
    pub safe_ports: String,
    #[yaserde(rename = "sslPorts")]
    pub ssl_ports: String,
    #[yaserde(rename = "remoteACLs")]
    pub remote_acls: RemoteAcls,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct RemoteAcls {
    pub blacklists: MaybeString,
    #[yaserde(rename = "UpdateCron")]
    pub update_cron: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Icap {
    pub enable: i32,
    #[yaserde(rename = "RequestURL")]
    pub request_url: String,
    #[yaserde(rename = "ResponseURL")]
    pub response_url: String,
    #[yaserde(rename = "SendClientIP")]
    pub send_client_ip: i32,
    #[yaserde(rename = "SendUsername")]
    pub send_username: i32,
    #[yaserde(rename = "EncodeUsername")]
    pub encode_username: i32,
    #[yaserde(rename = "UsernameHeader")]
    pub username_header: String,
    #[yaserde(rename = "EnablePreview")]
    pub enable_preview: i32,
    #[yaserde(rename = "PreviewSize")]
    pub preview_size: i32,
    #[yaserde(rename = "OptionsTTL")]
    pub options_ttl: i32,
    pub exclude: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Authentication {
    pub method: MaybeString,
    #[yaserde(rename = "authEnforceGroup")]
    pub auth_enforce_group: MaybeString,
    pub realm: String,
    pub credentialsttl: i32, // This field is already in snake_case
    pub children: i32,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Pac {}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct ErrorPages {
    pub template: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct ConfigSyslog {
    #[yaserde(attribute = true)]
    pub version: String,
    pub general: SyslogGeneral,
    pub destinations: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct SyslogGeneral {
    pub enabled: i32,
    pub loglocal: Option<MaybeString>,
    pub maxpreserve: Option<MaybeString>,
    pub maxfilesize: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct UnboundPlus {
    #[yaserde(attribute = true)]
    pub version: String,
    pub general: UnboundGeneral,
    pub advanced: Advanced,
    pub acls: Acls,
    pub dnsbl: Dnsbl,
    pub forwarding: Forwarding,
    pub dots: MaybeString,
    pub hosts: Hosts,
    pub aliases: MaybeString,
    pub domains: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct UnboundGeneral {
    pub enabled: i32,
    pub port: i32,
    pub stats: MaybeString,
    pub active_interface: MaybeString,
    pub dnssec: Option<MaybeString>,
    pub dns64: MaybeString,
    pub dns64prefix: MaybeString,
    pub noarecords: MaybeString,
    pub regdhcp: Option<i8>,
    pub regdhcpdomain: MaybeString,
    pub regdhcpstatic: Option<i8>,
    pub noreglladdr6: MaybeString,
    pub noregrecords: MaybeString,
    pub txtsupport: MaybeString,
    pub cacheflush: MaybeString,
    pub local_zone_type: String,
    pub outgoing_interface: MaybeString,
    pub enable_wpad: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Advanced {
    pub hideidentity: Option<i8>,
    pub hideversion: Option<i8>,
    pub prefetch: Option<i8>,
    pub prefetchkey: Option<i8>,
    pub dnssecstripped: Option<i8>,
    pub aggressivensec: Option<i8>,
    pub serveexpired: Option<i8>,
    pub serveexpiredreplyttl: MaybeString,
    pub serveexpiredttl: MaybeString,
    pub serveexpiredttlreset: Option<i32>,
    pub serveexpiredclienttimeout: MaybeString,
    pub qnameminstrict: Option<i32>,
    pub extendedstatistics: Option<i32>,
    pub logqueries: Option<i32>,
    pub logreplies: Option<i32>,
    pub logtagqueryreply: Option<i32>,
    pub logservfail: MaybeString,
    pub loglocalactions: MaybeString,
    pub logverbosity: i32,
    pub valloglevel: i32,
    pub privatedomain: MaybeString,
    pub privateaddress: MaybeString,
    pub insecuredomain: MaybeString,
    pub msgcachesize: MaybeString,
    pub rrsetcachesize: MaybeString,
    pub outgoingnumtcp: MaybeString,
    pub incomingnumtcp: MaybeString,
    pub numqueriesperthread: MaybeString,
    pub outgoingrange: MaybeString,
    pub jostletimeout: MaybeString,
    pub discardtimeout: Option<MaybeString>,
    pub cachemaxttl: MaybeString,
    pub cachemaxnegativettl: MaybeString,
    pub cacheminttl: MaybeString,
    pub infrahostttl: MaybeString,
    pub infrakeepprobing: MaybeString,
    pub infracachenumhosts: MaybeString,
    pub unwantedreplythreshold: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Acls {
    #[yaserde(rename = "default_action")]
    pub default_action: String,
    pub acl: Option<RawXml>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Dnsbl {
    pub enabled: i32,
    pub safesearch: MaybeString,
    #[yaserde(rename = "type")]
    pub r#type: MaybeString,
    pub lists: MaybeString,
    pub whitelists: MaybeString,
    pub blocklists: MaybeString,
    pub wildcards: MaybeString,
    pub address: MaybeString,
    pub nxdomain: Option<i32>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Forwarding {
    pub enabled: Option<i32>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Hosts {
    #[yaserde(rename = "host")]
    pub hosts: Vec<Host>,
}

#[derive(Default, Clone, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Host {
    #[yaserde(attribute = true)]
    pub uuid: String,
    pub enabled: i8,
    pub hostname: String,
    pub domain: String,
    pub rr: String,
    pub mxprio: MaybeString,
    pub mx: MaybeString,
    pub ttl: Option<MaybeString>,
    pub server: String,
    pub description: Option<String>,
}

impl Host {
    pub fn new(hostname: String, domain: String, rr: String, server: String) -> Self {
        Host {
            uuid: Uuid::new_v4().to_string(),
            enabled: true as i8,
            hostname,
            domain,
            rr,
            server,
            mxprio: MaybeString::default(),
            ttl: Some(MaybeString::default()),
            mx: MaybeString::default(),
            description: None,
        }
    }
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Wireguard {
    pub general: WireguardGeneral,
    pub server: WireguardServer,
    pub client: WireguardClient,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardGeneral {
    #[yaserde(attribute = true)]
    pub version: String,
    pub enabled: i32,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardServer {
    #[yaserde(attribute = true)]
    pub version: String,
    pub servers: WireguardServerList,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardServerList {
    pub server: Vec<WireguardServerItem>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardServerItem {
    #[yaserde(attribute = true)]
    pub uuid: String,
    pub enabled: i32,
    pub name: String,
    pub instance: i32,
    pub pubkey: String,
    pub privkey: String,
    pub port: i32,
    pub mtu: MaybeString,
    pub dns: MaybeString,
    pub tunneladdress: String,
    pub disableroutes: i32,
    pub gateway: MaybeString,
    pub carp_depend_on: MaybeString,
    pub peers: String,
    pub endpoint: MaybeString,
    pub peer_dns: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardClient {
    #[yaserde(attribute = true)]
    pub version: String,
    pub clients: WireguardClientList,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardClientList {
    pub client: Vec<WireguardClientItem>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct WireguardClientItem {
    #[yaserde(attribute = true)]
    pub uuid: String,
    pub enabled: i32,
    pub name: String,
    pub pubkey: String,
    pub psk: MaybeString,
    pub tunneladdress: String,
    pub serveraddress: MaybeString,
    pub serverport: MaybeString,
    pub keepalive: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Swanctl {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "Connections")]
    pub connections: MaybeString,
    pub locals: MaybeString,
    pub remotes: MaybeString,
    pub children: MaybeString,
    #[yaserde(rename = "Pools")]
    pub pools: MaybeString,
    #[yaserde(rename = "VTIs")]
    pub vtis: MaybeString,
    #[yaserde(rename = "SPDs")]
    pub spds: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
#[yaserde(rename = "DynDNS")]
pub struct DynDNS {
    #[yaserde(attribute = true)]
    pub version: String,
    pub general: DynDNSGeneral,
    pub accounts: Accounts,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct DynDNSGeneral {
    pub enabled: i32,
    pub verbose: i32,
    pub allowipv6: i32,
    pub daemon_delay: i32,
    pub backend: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Accounts {
    #[yaserde(rename = "account")]
    pub account: Account,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Account {
    #[yaserde(attribute = true)]
    pub uuid: String,
    pub enabled: i32,
    pub service: String,
    pub protocol: MaybeString,
    pub server: MaybeString,
    pub username: String,
    pub password: String,
    #[yaserde(rename = "resourceId")]
    pub resource_id: MaybeString,
    pub hostnames: String,
    pub wildcard: i32,
    pub zone: MaybeString,
    pub checkip: String,
    #[yaserde(rename = "checkip_timeout")]
    pub checkip_timeout: i32,
    #[yaserde(rename = "force_ssl")]
    pub force_ssl: i32,
    pub ttl: i32,
    pub interface: String,
    pub description: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct ConfigOpenVPN {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "Overwrites")]
    pub overwrites: MaybeString,
    #[yaserde(rename = "Instances")]
    pub instances: MaybeString,
    #[yaserde(rename = "StaticKeys")]
    pub static_keys: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct StaticRoutes {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "route")]
    pub route: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Ca {}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Cert {
    #[yaserde(attribute = true)]
    pub uuid: Option<String>,
    pub refid: String,
    pub descr: String,
    pub crt: String,
    pub caref: Option<MaybeString>,
    pub csr: Option<MaybeString>,
    pub prv: String,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct DhcpDv6 {} // Empty struct for <dhcpdv6/>

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct VirtualIp {
    #[yaserde(attribute = true)]
    pub version: String,
    #[yaserde(rename = "vip")]
    pub vip: Option<Vip>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Vip {
    #[yaserde(attribute = true)]
    pub uuid: Option<String>,
    pub interface: Option<MaybeString>,
    pub mode: Option<MaybeString>,
    pub subnet: Option<MaybeString>,
    pub subnet_bits: Option<MaybeString>,
    pub gateway: Option<MaybeString>,
    pub noexpand: Option<MaybeString>,
    pub nobind: Option<MaybeString>,
    pub password: Option<MaybeString>,
    pub vhid: Option<MaybeString>,
    pub advbase: Option<MaybeString>,
    pub advskew: Option<MaybeString>,
    pub descr: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct OpenVpn {
    #[yaserde(rename = "openvpn-server")]
    pub openvpn_server: Option<MaybeString>,
    #[yaserde(rename = "openvpn-client")]
    pub openvpn_client: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Ppps {
    pub ppp: Ppp,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Ppp {
    pub ptpid: Option<MaybeString>,
    #[yaserde(rename = "type")]
    pub r#type: Option<MaybeString>,
    #[yaserde(rename = "if")]
    pub r#if: Option<MaybeString>,
    pub ports: Option<MaybeString>,
    pub username: Option<MaybeString>,
    pub password: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Dyndnses {
    pub dyndns: Dyndns,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Dyndns {
    #[yaserde(rename = "type")]
    pub r#type: String,
    pub username: MaybeString,
    pub password: String,
    pub host: String,
    pub mx: MaybeString,
    pub interface: String,
    pub zoneid: MaybeString,
    pub resourceid: MaybeString,
    pub ttl: MaybeString,
    pub updateurl: MaybeString,
    pub resultmatch: MaybeString,
    pub requestif: String,
    pub descr: MaybeString,
    pub id: u32,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Vlans {
    #[yaserde(attribute = true)]
    pub version: String,
    pub vlan: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Bridges {
    pub bridged: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Gifs {
    #[yaserde(attribute = true)]
    pub version: Option<String>,
    pub gif: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Gres {
    #[yaserde(attribute = true)]
    pub version: Option<String>,
    pub gre: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Laggs {
    #[yaserde(attribute = true)]
    pub version: String,
    pub lagg: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Wireless {
    pub clone: MaybeString,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Hasync {
    #[yaserde(attribute = true)]
    pub version: Option<String>,
    pub synchronizealiases: Option<MaybeString>,
    pub synchronizeauthservers: Option<MaybeString>,
    pub synchronizecerts: Option<MaybeString>,
    pub synchronizedhcpd: Option<MaybeString>,
    pub synchronizenat: Option<MaybeString>,
    pub synchronizerules: Option<MaybeString>,
    pub synchronizeschedules: Option<MaybeString>,
    pub synchronizestaticroutes: Option<MaybeString>,
    pub synchronizeusers: Option<MaybeString>,
    pub synchronizevirtualip: Option<MaybeString>,
    pub synchronizewidgets: Option<MaybeString>,
    pub synchronizedhcrelay: Option<MaybeString>,
    pub synchronizedhcpdv6: Option<MaybeString>,
    pub synchronizedhcrelay6: Option<MaybeString>,
    pub synchronizentpd: Option<MaybeString>,
    pub synchronizesyslog: Option<MaybeString>,
    pub synchronizecron: Option<MaybeString>,
    pub synchronizesysctl: Option<MaybeString>,
    pub synchronizewebgui: Option<MaybeString>,
    pub synchronizednsforwarder: Option<MaybeString>,
    pub synchronizeshaper: Option<MaybeString>,
    pub synchronizecaptiveportal: Option<MaybeString>,
    pub synchronizeipsec: Option<MaybeString>,
    pub synchronizemonit: Option<MaybeString>,
    pub synchronizessh: Option<MaybeString>,
    pub synchronizeopenvpn: Option<MaybeString>,
    pub synchronizeifgroups: Option<MaybeString>,
    pub synchronizecategories: Option<MaybeString>,
    pub synchronizelvtemplate: Option<MaybeString>,
    pub synchronizesquid: Option<MaybeString>,
    pub synchronizesuricata: Option<MaybeString>,
    pub synchronizednsresolver: Option<MaybeString>,
    pub pfsyncinterface: Option<MaybeString>,
    pub synchronizetoip: Option<MaybeString>,
    pub verifypeer: Option<MaybeString>,
    pub username: Option<MaybeString>,
    pub password: Option<MaybeString>,
    pub pfsyncenabled: Option<MaybeString>,
    pub disablepreempt: Option<MaybeString>,
    pub disconnectppps: Option<MaybeString>,
    pub pfsyncpeerip: Option<MaybeString>,
    pub pfsyncversion: Option<MaybeString>,
    pub syncitems: Option<MaybeString>,
}

#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
pub struct Ifgroups {
    #[yaserde(attribute = true)]
    pub version: String,
}
