use anyhow::{anyhow, Result};

use crate::{
    protocol::modbus::generate_pull_set_holding_request,
    tui::{
        status as types,
        status::{
            port::{PortState, PortSubprocessInfo, PortSubprocessMode},
            {read_status, write_status},
        },
        utils::bus::{self, Bus, UiToCore},
    },
};

pub fn handle_enter_action(bus: &Bus) -> Result<()> {
    log::info!("🔵 handle_enter_action called");
    let current_cursor = read_status(|status| {
        if let crate::tui::status::Page::ModbusDashboard { cursor, .. } = &status.page {
            log::info!("🔵 Current cursor in ModbusDashboard: {cursor:?}");
            Ok(*cursor)
        } else {
            log::warn!("🔵 Not in ModbusDashboard page, using default AddLine cursor");
            Ok(types::cursor::ModbusDashboardCursor::AddLine)
        }
    })?;

    log::info!("🔵 Processing cursor action for: {current_cursor:?}");
    match current_cursor {
        types::cursor::ModbusDashboardCursor::AddLine => {
            log::info!("🔵 AddLine action - calling create_new_modbus_entry");
            create_new_modbus_entry(bus)?;
            log::info!("🔵 Station created successfully");

            // Move cursor to the new station's StationId field
            let new_station_index = read_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } =
                    &status.page
                {
                    if let Some(port_name) = status.ports.order.get(*selected_port) {
                        if let Some(port_entry) = status.ports.map.get(port_name) {
                            let port = port_entry;
                            let types::port::PortConfig::Modbus {
                                mode: _,
                                master_source: _,
                                stations,
                            } = &port.config;
                            return Ok(stations.len().saturating_sub(1));
                        }
                    }
                }
                Ok(0)
            })?;

            write_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { cursor, .. } = &mut status.page {
                    *cursor = types::cursor::ModbusDashboardCursor::StationId {
                        index: new_station_index,
                    };
                    log::info!("🔵 Moved cursor to new station StationId field (index: {new_station_index})");
                }
                Ok(())
            })?;

            log::info!("🔵 Sending refresh");
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            log::info!("🔵 Refresh sent");
        }
        types::cursor::ModbusDashboardCursor::ModbusMode => {
            // Toggle global mode for this port between Master and Slave
            let current_mode = read_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } =
                    &status.page
                {
                    if let Some(port_name) = status.ports.order.get(*selected_port) {
                        if let Some(port_entry) = status.ports.map.get(port_name) {
                            let port = port_entry;
                            let types::port::PortConfig::Modbus { mode, .. } = &port.config;
                            return Ok(if mode.is_master() { 0 } else { 1 });
                        }
                    }
                }
                Ok(0) // default to Master
            })?;

            write_status(|status| {
                status.temporarily.input_raw_buffer =
                    types::ui::InputRawBuffer::Index(current_mode);
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
        }
        types::cursor::ModbusDashboardCursor::MasterSourceKind => {
            let current_index = read_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } =
                    &status.page
                {
                    if let Some(port_name) = status.ports.order.get(*selected_port) {
                        if let Some(port_entry) = status.ports.map.get(port_name) {
                            let types::port::PortConfig::Modbus { master_source, .. } =
                                &port_entry.config;
                            return Ok(master_source.kind().to_index());
                        }
                    }
                }
                Ok(0)
            })?;

            write_status(|status| {
                status.temporarily.input_raw_buffer =
                    types::ui::InputRawBuffer::Index(current_index);
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
        }
        types::cursor::ModbusDashboardCursor::MasterSourceValue => {
            // Check if it's PortForwarding - use Index selector, otherwise use text input
            let (is_port_forwarding, current_source_port, all_ports, current_port) =
                read_status(|status| {
                    if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } =
                        &status.page
                    {
                        if let Some(port_name) = status.ports.order.get(*selected_port) {
                            if let Some(port_entry) = status.ports.map.get(port_name) {
                                let types::port::PortConfig::Modbus { master_source, .. } =
                                    &port_entry.config;
                                if let types::modbus::ModbusMasterDataSource::PortForwarding {
                                    source_port,
                                } = master_source
                                {
                                    return Ok((
                                        true,
                                        source_port.clone(),
                                        status.ports.order.clone(),
                                        port_name.clone(),
                                    ));
                                }
                            }
                        }
                    }
                    Ok((false, String::new(), vec![], String::new()))
                })?;

            if is_port_forwarding {
                // Use Index selector for PortForwarding
                let available_ports: Vec<String> = all_ports
                    .iter()
                    .filter(|p| p.as_str() != current_port)
                    .cloned()
                    .collect();

                if available_ports.is_empty() {
                    // No other ports available - do nothing (show greyed hint)
                    return Ok(());
                }

                // Find current index
                let current_index = available_ports
                    .iter()
                    .position(|p| p == &current_source_port)
                    .unwrap_or(0);

                write_status(|status| {
                    status.temporarily.input_raw_buffer =
                        types::ui::InputRawBuffer::Index(current_index);
                    Ok(())
                })?;
                bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
                return Ok(());
            }

            // For other data sources, use text input
            let current_text = read_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } =
                    &status.page
                {
                    if let Some(port_name) = status.ports.order.get(*selected_port) {
                        if let Some(port_entry) = status.ports.map.get(port_name) {
                            let types::port::PortConfig::Modbus { master_source, .. } =
                                &port_entry.config;
                            let value = match master_source {
                                types::modbus::ModbusMasterDataSource::MqttServer { url } => {
                                    url.clone()
                                }
                                types::modbus::ModbusMasterDataSource::HttpServer { port } => {
                                    port.to_string()
                                }
                                types::modbus::ModbusMasterDataSource::IpcPipe { path } => {
                                    path.clone()
                                }
                                _ => String::new(),
                            };
                            return Ok(value);
                        }
                    }
                }
                Ok(String::new())
            })?;

            let offset = current_text.chars().count() as isize;
            let buffer = types::ui::InputRawBuffer::String {
                bytes: current_text.into_bytes(),
                offset,
            };

            write_status(|status| {
                status.temporarily.input_raw_buffer = buffer.clone();
                Ok(())
            })?;

            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
        }
        types::cursor::ModbusDashboardCursor::RegisterMode { index } => {
            // Get the current register mode value from port config
            let current_value = read_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } =
                    &status.page
                {
                    if let Some(port_name) = status.ports.order.get(*selected_port) {
                        if let Some(port_entry) = status.ports.map.get(port_name) {
                            let port = port_entry;
                            let types::port::PortConfig::Modbus {
                                mode: _,
                                master_source: _,
                                stations,
                            } = &port.config;
                            let all_items: Vec<_> = stations.iter().collect();
                            if let Some(item) = all_items.get(index) {
                                return Ok((item.register_mode as u8 - 1) as usize);
                            }
                        }
                    }
                }
                Ok(2) // default to Holding
            })?;

            write_status(|status| {
                status.temporarily.input_raw_buffer =
                    types::ui::InputRawBuffer::Index(current_value);
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
        }
        types::cursor::ModbusDashboardCursor::StationId { .. }
        | types::cursor::ModbusDashboardCursor::RegisterStartAddress { .. }
        | types::cursor::ModbusDashboardCursor::RegisterLength { .. }
        | types::cursor::ModbusDashboardCursor::RequestInterval
        | types::cursor::ModbusDashboardCursor::Timeout => {
            write_status(|status| {
                status.temporarily.input_raw_buffer = types::ui::InputRawBuffer::String {
                    bytes: Vec::new(),
                    offset: 0,
                };
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
        }
        types::cursor::ModbusDashboardCursor::Register {
            slave_index,
            register_index,
        } => {
            let port_name_opt = read_status(|status| match &status.page {
                crate::tui::status::Page::ModbusDashboard { selected_port, .. } => {
                    Ok(status.ports.order.get(*selected_port).cloned())
                }
                _ => Ok(None),
            })?;

            if let Some(port_name) = port_name_opt {
                // Check if register editing is allowed
                // Master mode: only allow editing in Manual data source (no port state check)
                // Slave mode: only allow editing 01 (Coils) and 03 (Holding) registers AND port must be running
                let is_editable = read_status(|status| {
                    if let Some(port_entry) = status.ports.map.get(&port_name) {
                        let types::port::PortConfig::Modbus {
                            mode,
                            master_source,
                            stations,
                        } = &port_entry.config;

                        // Get the register mode of the current station
                        let register_mode = stations.get(slave_index).map(|s| s.register_mode);

                        // Check editability based on mode
                        match mode {
                            types::modbus::ModbusConnectionMode::Master => {
                                // Master mode: allow editing only in Manual data source
                                // No port state check - can edit even when not running
                                return Ok(matches!(
                                    master_source,
                                    types::modbus::ModbusMasterDataSource::Manual
                                ));
                            }
                            types::modbus::ModbusConnectionMode::Slave { .. } => {
                                // Slave mode: check port state first
                                if !matches!(port_entry.state, PortState::OccupiedByThis) {
                                    log::info!(
                                        "Slave mode: Register editing not allowed when port is not running (state={:?})",
                                        port_entry.state
                                    );
                                    return Ok(false);
                                }

                                // Slave mode: only allow editing 01 (Coils) and 03 (Holding) registers
                                // These represent the slave's own controllable outputs/state
                                // 02 (Discrete Inputs) and 04 (Input Registers) are read-only inputs
                                if let Some(reg_mode) = register_mode {
                                    return Ok(matches!(
                                        reg_mode,
                                        types::modbus::RegisterMode::Coils
                                            | types::modbus::RegisterMode::Holding
                                    ));
                                }
                                return Ok(false);
                            }
                        }
                    }
                    Ok(false)
                })?;

                if !is_editable {
                    // Don't allow editing based on mode and register type
                    log::info!(
                        "Register editing not allowed for this mode/register type combination"
                    );
                    return Ok(());
                }

                // Check if this register has a pending write
                let has_pending_write = read_status(|status| {
                    if let Some(port_entry) = status.ports.map.get(&port_name) {
                        let types::port::PortConfig::Modbus {
                            mode: _,
                            master_source: _,
                            stations,
                        } = &port_entry.config;
                        if let Some(station) = stations.get(slave_index) {
                            return Ok(station.pending_writes.contains_key(&register_index));
                        }
                    }
                    Ok(false)
                })?;

                if has_pending_write {
                    // Don't allow editing registers with pending writes
                    log::info!("Register editing locked - write in progress");
                    return Ok(());
                }

                // Get the register mode to determine behavior
                let register_mode = read_status(|status| {
                    if let Some(port_entry) = status.ports.map.get(&port_name) {
                        let port = port_entry;
                        let types::port::PortConfig::Modbus {
                            mode: _,
                            master_source: _,
                            stations,
                        } = &port.config;
                        let all_items: Vec<_> = stations.iter().collect();
                        if let Some(item) = all_items.get(slave_index) {
                            return Ok(Some(item.register_mode));
                        }
                    }
                    Ok(None)
                })?;

                if let Some(mode) = register_mode {
                    match mode {
                        types::modbus::RegisterMode::Coils
                        | types::modbus::RegisterMode::DiscreteInputs => {
                            // Toggle coil value
                            let selected_port = read_status(|status| {
                                if let crate::tui::status::Page::ModbusDashboard {
                                    selected_port,
                                    ..
                                } = &status.page
                                {
                                    Ok(*selected_port)
                                } else {
                                    Ok(0)
                                }
                            })?;

                            let port_name_opt = read_status(|status| {
                                Ok(status.ports.order.get(selected_port).cloned())
                            })?;

                            if let Some(port_name) = port_name_opt {
                                if let Some(_port) = read_status(|status| {
                                    Ok(status.ports.map.get(&port_name).cloned())
                                })? {
                                    let mut subprocess_info_snapshot: Option<PortSubprocessInfo> =
                                        None;
                                    let mut register_update: Option<(String, u8, u16, Vec<u16>)> =
                                        None;

                                    write_status(|status| {
                                        let port = status
                                            .ports
                                            .map
                                            .get_mut(&port_name)
                                            .ok_or_else(|| anyhow::anyhow!("Port not found"))?;
                                        subprocess_info_snapshot = port.subprocess_info.clone();

                                        let types::port::PortConfig::Modbus {
                                            mode,
                                            master_source: _,
                                            stations,
                                        } = &mut port.config;
                                        if let Some(item) = stations.get_mut(slave_index) {
                                            let register_addr =
                                                item.register_address + register_index as u16;

                                            let value_index =
                                                (register_addr - item.register_address) as usize;
                                            if item.last_values.len() <= value_index {
                                                item.last_values.resize(value_index + 1, 0);
                                            }

                                            let current = item.last_values[value_index] != 0;
                                            let new_value_flag = !current;
                                            item.last_values[value_index] =
                                                if new_value_flag { 1 } else { 0 };

                                            match mode {
                                                types::modbus::ModbusConnectionMode::Master => {
                                                    register_update = Some((
                                                        "coil".to_string(),
                                                        item.station_id,
                                                        register_addr,
                                                        vec![item.last_values[value_index]],
                                                    ));
                                                }
                                                types::modbus::ModbusConnectionMode::Slave {
                                                    ..
                                                } => {
                                                    let should_queue = !matches!(
                                                        subprocess_info_snapshot.as_ref(),
                                                        Some(info)
                                                            if info.mode == PortSubprocessMode::MasterProvide
                                                    );

                                                    if should_queue {
                                                        let coil_value = if new_value_flag {
                                                            0xFF00
                                                        } else {
                                                            0x0000
                                                        };

                                                        if let Ok((_request, raw_frame)) =
                                                            generate_pull_set_holding_request(
                                                                item.station_id,
                                                                register_addr,
                                                                coil_value,
                                                            )
                                                        {
                                                            let mut frame = raw_frame;
                                                            if frame.len() > 1 {
                                                                frame[1] = 0x05;
                                                                // single coil write
                                                            }
                                                            item.pending_requests
                                                                .extend_from_slice(&frame);
                                                            log::info!(
                                                                "📤 Slave: Queued coil toggle 0x{:04X} -> {} ({} bytes)",
                                                                register_addr,
                                                                new_value_flag,
                                                                frame.len()
                                                            );
                                                        } else {
                                                            log::warn!(
                                                                "Failed to build single-coil write frame for station {}",
                                                                item.station_id
                                                            );
                                                        }
                                                    }

                                                    register_update = Some((
                                                        "coil".to_string(),
                                                        item.station_id,
                                                        register_addr,
                                                        vec![item.last_values[value_index]],
                                                    ));
                                                }
                                            }
                                        }
                                        Ok(())
                                    })?;

                                    if let (Some(_), Some(update)) =
                                        (subprocess_info_snapshot, register_update)
                                    {
                                        if let Err(err) =
                                            bus.ui_tx.send(UiToCore::SendRegisterUpdate {
                                                port_name: port_name.clone(),
                                                station_id: update.1,
                                                register_type: update.0,
                                                start_address: update.2,
                                                values: update.3,
                                            })
                                        {
                                            log::warn!(
                                                "Failed to send coil toggle IPC message: {err}"
                                            );
                                        }
                                    }
                                }
                            }
                            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
                        }
                        types::modbus::RegisterMode::Holding
                        | types::modbus::RegisterMode::Input => {
                            // Enter edit mode for numeric registers with empty buffer
                            // (User will type the new value from scratch)
                            write_status(|status| {
                                status.temporarily.input_raw_buffer =
                                    types::ui::InputRawBuffer::String {
                                        bytes: Vec::new(),
                                        offset: 0,
                                    };
                                Ok(())
                            })?;
                            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
                        }
                    }
                }
            }
        }
    }
    Ok(())
}

pub fn handle_leave_page(bus: &Bus) -> Result<()> {
    log::info!("🟦 handle_leave_page called");

    let selected_port = read_status(|status| {
        if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } = &status.page {
            Ok(*selected_port)
        } else {
            Ok(0)
        }
    })?;

    log::info!("🟦 Selected port index: {selected_port}");

    // Check if we need to restart the runtime or auto-enable the port
    let (port_name, should_restart, should_auto_enable, has_stations) = read_status(|status| {
        let port_name = status.ports.order.get(selected_port).cloned();
        log::info!("🟦 Port name: {port_name:?}");

        let (should_restart, should_auto_enable, has_stations) = if let Some(name) = &port_name {
            let port_data = status.ports.map.get(name);
            let port_state = port_data.as_ref().map(|p| {
                let port = p;
                log::info!("🟦 Port state: {:?}", port.state);
                port.state.clone()
            });
            let needs_restart = port_data
                .as_ref()
                .map(|p| p.config_modified)
                .unwrap_or(false);

            // Check if port has subprocess info (CLI subprocess)
            let has_subprocess_info = port_data
                .as_ref()
                .map(|p| p.subprocess_info.is_some())
                .unwrap_or(false);

            // Check if port has any stations configured
            let has_stations = port_data
                .as_ref()
                .map(|p| {
                    let port = p;
                    let types::port::PortConfig::Modbus { stations, .. } = &port.config;
                    let _count = stations.len();

                    !stations.is_empty()
                })
                .unwrap_or(false);

            // TUI only uses CLI subprocesses. Check if port has subprocess info.
            let should_restart = matches!(port_state, Some(types::port::PortState::OccupiedByThis))
                && has_subprocess_info
                && needs_restart;

            // Auto-enable if: port is Free AND has stations configured
            let should_auto_enable =
                matches!(port_state, Some(types::port::PortState::Free)) && has_stations;

            log::info!(
                "🟦 Should restart: {should_restart}, Should auto-enable: {should_auto_enable}, Has stations: {has_stations}, Needs restart: {needs_restart}"
            );
            (should_restart, should_auto_enable, has_stations)
        } else {
            log::info!("🟦 No port name, should_restart=false, should_auto_enable=false");
            (false, false, false)
        };

        Ok((port_name, should_restart, should_auto_enable, has_stations))
    })?;

    // If port is running, restart it to apply the new configuration
    if should_restart {
        if let Some(name) = &port_name {
            log::info!("🔄 Restarting runtime for {name} to apply Modbus configuration changes");
            bus.ui_tx
                .send(UiToCore::RestartRuntime(name.clone()))
                .map_err(|err| anyhow!("Failed to send RestartRuntime: {err}"))?;
        }
    }
    // Auto-enable port if it's free and has stations configured
    else if should_auto_enable {
        if let Some(name) = &port_name {
            log::info!(
                "🚀 Auto-enabling port {name} with {} station(s) configured",
                if has_stations { "valid" } else { "no" }
            );
            bus.ui_tx
                .send(UiToCore::ToggleRuntime(name.clone()))
                .map_err(|err| anyhow!("Failed to send ToggleRuntime for auto-enable: {err}"))?;
        }
    }

    // Save configuration before leaving the page
    if let Err(e) = save_current_configs() {
        log::warn!("Failed to save port configurations: {e}");
    }

    if let Some(name) = &port_name {
        write_status(|status| {
            if let Some(port) = status.ports.map.get_mut(name) {
                port.config_modified = false;
            }
            Ok(())
        })?;
    }

    write_status(|status| {
        status.page = crate::tui::status::Page::ConfigPanel {
            selected_port,
            view_offset: 0,
            cursor: types::cursor::ConfigPanelCursor::EnablePort,
        };
        Ok(())
    })?;
    bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
    Ok(())
}

fn create_new_modbus_entry(_bus: &Bus) -> Result<()> {
    log::info!("🟢 create_new_modbus_entry called");
    let selected_port = read_status(|status| {
        if let crate::tui::status::Page::ModbusDashboard { selected_port, .. } = &status.page {
            log::info!("🟢 Selected port index: {selected_port}");
            Ok(*selected_port)
        } else {
            log::warn!("🟢 Not in ModbusDashboard page, using default port 0");
            Ok(0)
        }
    })?;

    let port_name_opt = read_status(|status| {
        let name = status.ports.order.get(selected_port).cloned();
        log::info!("🟢 Port name at index {selected_port}: {name:?}");
        Ok(name)
    })?;

    if let Some(port_name) = port_name_opt {
        log::info!("🟢 Found port name: {port_name}");
        let mut should_restart_runtime = false;
        if let Some(_port) = read_status(|status| {
            let port = status.ports.map.get(&port_name).cloned();
            if port.is_some() {
                log::info!("🟢 Port entry found in map for: {port_name}");
            } else {
                log::warn!("🟢 Port entry NOT found in map for: {port_name}");
            }
            Ok(port)
        })? {
            log::info!("🟢 Calling write_status for: {port_name}");
            write_status(|status| {
                let port = status
                    .ports
                    .map
                    .get_mut(&port_name)
                    .ok_or_else(|| anyhow::anyhow!("Port not found"))?;
                log::info!("🟢 Inside write_status closure");
                // Check if port is currently occupied before adding station
                // TUI only uses CLI subprocesses
                if matches!(port.state, PortState::OccupiedByThis) {
                    log::info!(
                        "🟢 Port {port_name} is occupied by CLI subprocess - scheduling restart"
                    );
                    should_restart_runtime = true;
                }

                let types::port::PortConfig::Modbus {
                    mode,
                    master_source: _,
                    stations,
                } = &mut port.config;
                log::info!(
                    "🟢 Current mode: {:?}, current stations count: {}",
                    if mode.is_master() { "Master" } else { "Slave" },
                    stations.len()
                );
                // Create a new entry with the global mode from the port config
                let new_entry = types::modbus::ModbusRegisterItem {
                    station_id: 1,
                    register_mode: types::modbus::RegisterMode::Holding,
                    register_address: 0,
                    register_length: 1,
                    last_values: vec![0],
                    req_success: 0,
                    req_total: 0,
                    next_poll_at: std::time::Instant::now() - std::time::Duration::from_secs(1), // Start immediately
                    last_request_time: None,
                    last_response_time: None,
                    pending_requests: Vec::new(),
                    pending_writes: std::collections::HashMap::new(),
                };
                log::info!("🟢 Pushing new station entry");
                stations.push(new_entry);
                log::info!(
                    "✅ Created new modbus entry with station_id=1 in {:?} mode (total stations now: {})",
                    if mode.is_master() { "Master" } else { "Slave" },
                    stations.len()
                );
                Ok(())
            })?;
            log::info!("🟢 write_status completed");

            // Save configuration to disk
            if let Err(e) = save_current_configs() {
                log::warn!("Failed to save port configurations: {e}");
            }

            // NOTE: Removed automatic restart when creating new station
            // Restart will be triggered when user saves configuration (presses Esc)
            // This allows users to configure multiple stations before restarting
            if should_restart_runtime {
                log::info!("🔄 Port {port_name} runtime needs restart (deferred until save)");
            }
            // The restart logic has been moved to handle_leave_page() function
        } else {
            log::error!("🟢 Port entry is None for: {port_name}");
        }
    } else {
        log::error!("🟢 Port name is None at selected_port index: {selected_port}");
    }
    log::info!("🟢 create_new_modbus_entry completed");
    Ok(())
}

/// Helper function to save current port configurations to disk
fn save_current_configs() -> Result<()> {
    use std::collections::HashMap;

    let configs: HashMap<String, types::port::PortConfig> = read_status(|status| {
        let mut map = HashMap::new();
        for (name, port_arc) in &status.ports.map {
            let port = port_arc;
            // Only save Modbus ports with stations
            let types::port::PortConfig::Modbus { stations, .. } = &port.config;
            if !stations.is_empty() {
                map.insert(name.clone(), port.config.clone());
            }
        }
        Ok(map)
    })?;

    if !configs.is_empty() {
        crate::tui::persistence::save_port_configs(&configs)?;
    }

    Ok(())
}
