use anyhow::{anyhow, Result};

use crossterm::event::{KeyCode, KeyEvent};

use super::actions::{handle_enter_action, handle_leave_page};
use crate::{
    tui::{
        status as types,
        status::{
            cursor::Cursor,
            {read_status, write_status},
        },
        utils::bus::{self, Bus, UiToCore},
    },
    utils::i18n::lang,
};

pub fn handle_navigation_input(key: KeyEvent, bus: &Bus) -> Result<()> {
    log::info!("🟠 ModbusDashboard navigation input: {:?}", key.code);

    // Check for Ctrl modifier
    let has_ctrl = key
        .modifiers
        .contains(crossterm::event::KeyModifiers::CONTROL);

    // Handle Ctrl+S for saving configuration
    if matches!(key.code, KeyCode::Char('s') | KeyCode::Char('S')) && has_ctrl {
        log::info!("💾 Ctrl+S pressed - saving configuration and enabling port");
        // This will trigger port enable with current configuration
        handle_save_config(bus)?;
        return Ok(());
    }

    match key.code {
        KeyCode::PageUp => {
            if has_ctrl {
                // Ctrl+PageUp: Jump to first group (AddLine)
                let new_cursor = types::cursor::ModbusDashboardCursor::AddLine;
                let new_offset = new_cursor.view_offset();
                write_status(|status| {
                    if let crate::tui::status::Page::ModbusDashboard {
                        cursor,
                        view_offset,
                        ..
                    } = &mut status.page
                    {
                        *cursor = new_cursor;
                        *view_offset = new_offset;
                    }
                    Ok(())
                })?;
            } else {
                // PageUp: Jump to previous station group
                let current_cursor = read_status(|status| match &status.page {
                    crate::tui::status::Page::ModbusDashboard { cursor, .. } => Ok(*cursor),
                    _ => Ok(types::cursor::ModbusDashboardCursor::AddLine),
                })?;

                let new_cursor = jump_to_prev_group(current_cursor)?;
                let new_offset = new_cursor.view_offset();
                write_status(|status| {
                    if let crate::tui::status::Page::ModbusDashboard {
                        cursor,
                        view_offset,
                        ..
                    } = &mut status.page
                    {
                        *cursor = new_cursor;
                        *view_offset = new_offset;
                    }
                    Ok(())
                })?;
            }
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            Ok(())
        }
        KeyCode::PageDown => {
            if has_ctrl {
                // Ctrl+PageDown: Jump to last group (first item of last station if exists)
                let new_cursor = jump_to_last_group()?;
                let new_offset = new_cursor.view_offset();
                write_status(|status| {
                    if let crate::tui::status::Page::ModbusDashboard {
                        cursor,
                        view_offset,
                        ..
                    } = &mut status.page
                    {
                        *cursor = new_cursor;
                        *view_offset = new_offset;
                    }
                    Ok(())
                })?;
            } else {
                // PageDown: Jump to next station group
                let current_cursor = read_status(|status| match &status.page {
                    crate::tui::status::Page::ModbusDashboard { cursor, .. } => Ok(*cursor),
                    _ => Ok(types::cursor::ModbusDashboardCursor::AddLine),
                })?;

                let new_cursor = jump_to_next_group(current_cursor)?;
                let new_offset = new_cursor.view_offset();
                write_status(|status| {
                    if let crate::tui::status::Page::ModbusDashboard {
                        cursor,
                        view_offset,
                        ..
                    } = &mut status.page
                    {
                        *cursor = new_cursor;
                        *view_offset = new_offset;
                    }
                    Ok(())
                })?;
            }
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            Ok(())
        }
        KeyCode::Left | KeyCode::Char('h') => {
            let current_cursor = read_status(|status| match &status.page {
                crate::tui::status::Page::ModbusDashboard { cursor, .. } => Ok(*cursor),
                _ => Ok(types::cursor::ModbusDashboardCursor::AddLine),
            })?;

            // Handle horizontal navigation for register table
            let new_cursor = match current_cursor {
                types::cursor::ModbusDashboardCursor::Register {
                    slave_index,
                    register_index,
                } => {
                    if register_index > 0 {
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index,
                            register_index: register_index - 1,
                        }
                    } else {
                        // At the first register, jump to RegisterLength
                        types::cursor::ModbusDashboardCursor::RegisterLength { index: slave_index }
                    }
                }
                _ => current_cursor.prev(),
            };

            let new_offset = new_cursor.view_offset();
            write_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard {
                    cursor,
                    view_offset,
                    ..
                } = &mut status.page
                {
                    *cursor = new_cursor;
                    *view_offset = new_offset;
                }
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            Ok(())
        }
        KeyCode::Right | KeyCode::Char('l') => {
            let current_cursor = read_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard { cursor, .. } = &status.page {
                    Ok(*cursor)
                } else {
                    Ok(types::cursor::ModbusDashboardCursor::AddLine)
                }
            })?;

            // Handle horizontal navigation for register table
            let new_cursor = match current_cursor {
                types::cursor::ModbusDashboardCursor::Register {
                    slave_index,
                    register_index,
                } => {
                    // Get register length and check if there's a next station
                    let (max_register, has_next_station) = read_status(|status| {
                        let port_name_opt = match &status.page {
                            crate::tui::status::Page::ModbusDashboard { selected_port, .. } => {
                                status.ports.order.get(*selected_port).cloned()
                            }
                            _ => None,
                        };
                        if let Some(port_name) = port_name_opt {
                            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) {
                                    let has_next = slave_index + 1 < all_items.len();
                                    return Ok((item.register_length as usize, has_next));
                                }
                            }
                        }
                        Ok((0, false))
                    })?;

                    if register_index + 1 < max_register {
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index,
                            register_index: register_index + 1,
                        }
                    } else if has_next_station {
                        // Jump to next station's first register
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index: slave_index + 1,
                            register_index: 0,
                        }
                    } else {
                        // Stay at current position
                        current_cursor
                    }
                }
                _ => current_cursor.next(),
            };

            let new_offset = new_cursor.view_offset();
            write_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard {
                    cursor,
                    view_offset,
                    ..
                } = &mut status.page
                {
                    *cursor = new_cursor;
                    *view_offset = new_offset;
                }
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            Ok(())
        }
        KeyCode::Up | KeyCode::Char('k') => {
            let current_cursor = read_status(|status| match &status.page {
                crate::tui::status::Page::ModbusDashboard { cursor, .. } => Ok(*cursor),
                _ => Ok(types::cursor::ModbusDashboardCursor::AddLine),
            })?;

            // Handle vertical navigation for register table with dynamic registers per row
            let new_cursor = match current_cursor {
                types::cursor::ModbusDashboardCursor::Register {
                    slave_index,
                    register_index,
                } => {
                    // Use 4 registers per row for 80-column terminals
                    let registers_per_row = 4;

                    // Get register length
                    let _max_register = read_status(|status| {
                        let port_name_opt = match &status.page {
                            crate::tui::status::Page::ModbusDashboard { selected_port, .. } => {
                                status.ports.order.get(*selected_port).cloned()
                            }
                            _ => None,
                        };
                        if let Some(port_name) = port_name_opt {
                            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(item.register_length as usize);
                                }
                            }
                        }
                        Ok(0)
                    })?;

                    if register_index >= registers_per_row {
                        // Move up by registers_per_row
                        let target_index = register_index.saturating_sub(registers_per_row);
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index,
                            register_index: target_index,
                        }
                    } else if register_index > 0 {
                        // In first row but not at index 0, jump to first register
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index,
                            register_index: 0,
                        }
                    } else {
                        // At first register, jump to RegisterLength
                        types::cursor::ModbusDashboardCursor::RegisterLength { index: slave_index }
                    }
                }
                _ => current_cursor.prev(),
            };

            let new_offset = new_cursor.view_offset();
            write_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard {
                    cursor,
                    view_offset,
                    ..
                } = &mut status.page
                {
                    *cursor = new_cursor;
                    *view_offset = new_offset;
                }
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            Ok(())
        }
        KeyCode::Down | KeyCode::Char('j') => {
            let current_cursor = read_status(|status| match &status.page {
                crate::tui::status::Page::ModbusDashboard { cursor, .. } => Ok(*cursor),
                _ => Ok(types::cursor::ModbusDashboardCursor::AddLine),
            })?;

            // Handle vertical navigation for register table with 8-register row alignment
            let new_cursor = match current_cursor {
                types::cursor::ModbusDashboardCursor::Register {
                    slave_index,
                    register_index,
                } => {
                    // Use 4 registers per row for 80-column terminals
                    let registers_per_row = 4;

                    // Get register length and check if there's a next station
                    let (max_register, has_next_slave) = read_status(|status| {
                        let port_name_opt = match &status.page {
                            crate::tui::status::Page::ModbusDashboard { selected_port, .. } => {
                                status.ports.order.get(*selected_port).cloned()
                            }
                            _ => None,
                        };
                        if let Some(port_name) = port_name_opt {
                            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) {
                                    let has_next = slave_index + 1 < all_items.len();
                                    return Ok((item.register_length as usize, has_next));
                                }
                            }
                        }
                        Ok((0, false))
                    })?;

                    let target_index = register_index + registers_per_row;

                    if target_index < max_register {
                        // Normal case: move down by registers_per_row
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index,
                            register_index: target_index,
                        }
                    } else if register_index < max_register - 1 {
                        // Target goes beyond, but not at last register yet
                        // Jump to last register
                        types::cursor::ModbusDashboardCursor::Register {
                            slave_index,
                            register_index: max_register - 1,
                        }
                    } else {
                        // At last register
                        if has_next_slave {
                            // Jump to next station's first register
                            types::cursor::ModbusDashboardCursor::Register {
                                slave_index: slave_index + 1,
                                register_index: 0,
                            }
                        } else {
                            // Stay at last register
                            current_cursor
                        }
                    }
                }
                _ => current_cursor.next(),
            };

            let new_offset = new_cursor.view_offset();
            write_status(|status| {
                if let crate::tui::status::Page::ModbusDashboard {
                    cursor,
                    view_offset,
                    ..
                } = &mut status.page
                {
                    *cursor = new_cursor;
                    *view_offset = new_offset;
                }
                Ok(())
            })?;
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
            Ok(())
        }
        KeyCode::Enter => {
            log::info!("🟠 Enter key pressed in ModbusDashboard");
            handle_enter_action(bus)?;
            log::info!("🟠 handle_enter_action completed successfully");
            Ok(())
        }
        KeyCode::Delete => {
            // Handle delete key functionality here
            Ok(())
        }
        KeyCode::Esc => {
            handle_leave_page(bus)?;
            Ok(())
        }
        _ => Ok(()),
    }
}

/// Handle saving configuration with Ctrl+S
/// This marks the config as saved and triggers port enable if not already enabled
fn handle_save_config(bus: &Bus) -> Result<()> {
    use chrono::Local;

    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()))? {
            // Check if port has any stations configured
            let has_stations = match &port.config {
                types::port::PortConfig::Modbus { stations, .. } => !stations.is_empty(),
            };

            if !has_stations {
                // Show error if no stations configured
                write_status(|status| {
                    status.temporarily.error = Some(crate::tui::status::ErrorInfo {
                        message: lang().index.err_modbus_config_empty.clone(),
                        timestamp: Local::now(),
                    });
                    Ok(())
                })?;
                bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
                return Ok(());
            }

            // Validate data source configuration in master mode
            let types::port::PortConfig::Modbus {
                mode,
                master_source,
                ..
            } = &port.config;
            if mode.is_master() {
                if let Err(validation_error) = validate_data_source(master_source) {
                    let err_msg = validation_error.clone();
                    write_status(|status| {
                        status.temporarily.error = Some(crate::tui::status::ErrorInfo {
                            message: err_msg.clone(),
                            timestamp: Local::now(),
                        });
                        Ok(())
                    })?;
                    bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;
                    return Ok(());
                }
            }

            // Mark config as applied and check whether a restart is required
            let (is_enabled, needs_restart) = write_status(|status| {
                let port = status
                    .ports
                    .map
                    .get_mut(&port_name)
                    .ok_or_else(|| anyhow::anyhow!("Port not found"))?;

                let is_enabled = matches!(port.state, types::port::PortState::OccupiedByThis);
                let needs_restart = is_enabled && port.config_modified;

                if !is_enabled {
                    // Port not running: show "已应用" success status
                    port.status_indicator = types::port::PortStatusIndicator::AppliedSuccess {
                        timestamp: Local::now(),
                    };
                    port.config_modified = false;
                } else if needs_restart {
                    // Port running and needs restart: show "重启中" status
                    // Note: Don't clear config_modified yet - restart_runtime() will do it
                    port.status_indicator = types::port::PortStatusIndicator::Restarting;
                } else {
                    // Port running and no changes: keep current status
                    port.config_modified = false;
                }

                Ok((is_enabled, needs_restart))
            })?;

            // Trigger immediate UI refresh to show status change
            bus::request_refresh(&bus.ui_tx).map_err(|err| anyhow!(err))?;

            if !is_enabled {
                // Enable the port if not already enabled
                log::info!("Port not enabled, triggering enable via ToggleRuntime");
                bus.ui_tx
                    .send(UiToCore::ToggleRuntime(port_name.clone()))
                    .map_err(|err| anyhow!(err))?;
            } else if needs_restart {
                // Port already enabled, just restart it with new config
                log::info!("Port already enabled, restarting with new config");
                bus.ui_tx
                    .send(UiToCore::RestartRuntime(port_name))
                    .map_err(|err| anyhow!(err))?;
            } else {
                log::info!("Port already enabled and runtime up-to-date; skipping restart");
            }
        }
    }

    Ok(())
}

/// Jump to previous station group
/// - If on AddLine or ModbusMode, stay at AddLine (first group)
/// - If on a station's item, jump to previous station's first item (StationId)
/// - If on first station, jump to ModbusMode
fn jump_to_prev_group(
    current_cursor: types::cursor::ModbusDashboardCursor,
) -> Result<types::cursor::ModbusDashboardCursor> {
    match current_cursor {
        types::cursor::ModbusDashboardCursor::AddLine => {
            // Already at first group
            Ok(types::cursor::ModbusDashboardCursor::AddLine)
        }
        types::cursor::ModbusDashboardCursor::ModbusMode => {
            // Jump to AddLine
            Ok(types::cursor::ModbusDashboardCursor::AddLine)
        }
        types::cursor::ModbusDashboardCursor::MasterSourceKind => {
            Ok(types::cursor::ModbusDashboardCursor::ModbusMode)
        }
        types::cursor::ModbusDashboardCursor::MasterSourceValue => {
            Ok(types::cursor::ModbusDashboardCursor::MasterSourceKind)
        }
        types::cursor::ModbusDashboardCursor::RequestInterval => {
            // Jump to AddLine
            Ok(types::cursor::ModbusDashboardCursor::AddLine)
        }
        types::cursor::ModbusDashboardCursor::Timeout => {
            // Jump to AddLine
            Ok(types::cursor::ModbusDashboardCursor::AddLine)
        }
        types::cursor::ModbusDashboardCursor::StationId { index }
        | types::cursor::ModbusDashboardCursor::RegisterMode { index }
        | types::cursor::ModbusDashboardCursor::RegisterStartAddress { index }
        | types::cursor::ModbusDashboardCursor::RegisterLength { index }
        | types::cursor::ModbusDashboardCursor::Register {
            slave_index: index, ..
        } => {
            if index == 0 {
                // Jump to ModbusMode (second item in first group)
                Ok(types::cursor::ModbusDashboardCursor::ModbusMode)
            } else {
                // Jump to previous station's first item
                Ok(types::cursor::ModbusDashboardCursor::StationId { index: index - 1 })
            }
        }
    }
}

/// Jump to next station group
/// - If on AddLine, jump to ModbusMode
/// - If on ModbusMode, jump to first station (if exists) or stay at ModbusMode
/// - If on a station's item, jump to next station's first item (if exists) or stay
fn jump_to_next_group(
    current_cursor: types::cursor::ModbusDashboardCursor,
) -> Result<types::cursor::ModbusDashboardCursor> {
    match current_cursor {
        types::cursor::ModbusDashboardCursor::AddLine => {
            // Jump to ModbusMode
            Ok(types::cursor::ModbusDashboardCursor::ModbusMode)
        }
        types::cursor::ModbusDashboardCursor::ModbusMode => {
            // Check if we're in slave mode and should jump to RequestInterval, or jump to first station
            let is_slave = 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_data) = status.ports.map.get(port_name) {
                            let types::port::PortConfig::Modbus { mode, .. } = &port_data.config;
                            return Ok(mode.is_slave());
                        }
                    }
                }
                Ok(false)
            })?;

            if is_slave {
                // Jump to RequestInterval
                Ok(types::cursor::ModbusDashboardCursor::RequestInterval)
            } else {
                Ok(types::cursor::ModbusDashboardCursor::MasterSourceKind)
            }
        }
        types::cursor::ModbusDashboardCursor::MasterSourceKind => {
            let (has_value_field, has_stations) = 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,
                                stations,
                                ..
                            } = &port_entry.config;
                            let value_kind = master_source.value_kind();
                            let has_value = !matches!(
                                value_kind,
                                types::modbus::ModbusMasterDataSourceValueKind::None
                            );
                            return Ok((has_value, !stations.is_empty()));
                        }
                    }
                }
                Ok((false, false))
            })?;

            if has_value_field {
                Ok(types::cursor::ModbusDashboardCursor::MasterSourceValue)
            } else if has_stations {
                Ok(types::cursor::ModbusDashboardCursor::StationId { index: 0 })
            } else {
                Ok(types::cursor::ModbusDashboardCursor::MasterSourceKind)
            }
        }
        types::cursor::ModbusDashboardCursor::MasterSourceValue => {
            let has_stations = 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 { stations, .. } =
                                &port_entry.config;
                            return Ok(!stations.is_empty());
                        }
                    }
                }
                Ok(false)
            })?;

            if has_stations {
                Ok(types::cursor::ModbusDashboardCursor::StationId { index: 0 })
            } else {
                Ok(types::cursor::ModbusDashboardCursor::MasterSourceValue)
            }
        }
        types::cursor::ModbusDashboardCursor::RequestInterval
        | types::cursor::ModbusDashboardCursor::Timeout => {
            // Jump to first station if exists
            let has_stations = 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.is_empty());
                        }
                    }
                }
                Ok(false)
            })?;

            if has_stations {
                Ok(types::cursor::ModbusDashboardCursor::StationId { index: 0 })
            } else {
                // No stations, stay at current
                Ok(current_cursor)
            }
        }
        types::cursor::ModbusDashboardCursor::StationId { index }
        | types::cursor::ModbusDashboardCursor::RegisterMode { index }
        | types::cursor::ModbusDashboardCursor::RegisterStartAddress { index }
        | types::cursor::ModbusDashboardCursor::RegisterLength { index }
        | types::cursor::ModbusDashboardCursor::Register {
            slave_index: index, ..
        } => {
            // Check if next station exists
            let has_next = 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();
                            return Ok(index + 1 < all_items.len());
                        }
                    }
                }
                Ok(false)
            })?;

            if has_next {
                Ok(types::cursor::ModbusDashboardCursor::StationId { index: index + 1 })
            } else {
                // Stay at current station's first item
                Ok(types::cursor::ModbusDashboardCursor::StationId { index })
            }
        }
    }
}

/// Jump to last station group (first item of last station if exists, otherwise ModbusMode)
fn jump_to_last_group() -> Result<types::cursor::ModbusDashboardCursor> {
    let last_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;
                    let all_items: Vec<_> = stations.iter().collect();
                    if !all_items.is_empty() {
                        return Ok(Some(all_items.len() - 1));
                    }
                }
            }
        }
        Ok(None)
    })?;

    if let Some(index) = last_station_index {
        Ok(types::cursor::ModbusDashboardCursor::StationId { index })
    } else {
        // No stations, stay at ModbusMode
        Ok(types::cursor::ModbusDashboardCursor::ModbusMode)
    }
}

/// Validate data source configuration
/// Returns Ok(()) if valid, Err(message) if invalid
fn validate_data_source(source: &types::modbus::ModbusMasterDataSource) -> Result<(), String> {
    match source {
        types::modbus::ModbusMasterDataSource::Manual => Ok(()),
        types::modbus::ModbusMasterDataSource::MqttServer { url } => {
            if url.is_empty() {
                return Ok(()); // Allow empty URL, will use placeholder
            }
            validate_url(url, "mqtt")
        }
        types::modbus::ModbusMasterDataSource::HttpServer { port } => {
            // Validate port number range (1-65535)
            if *port == 0 {
                return Err("Port number must be between 1 and 65535".to_string());
            }
            Ok(())
        }
        types::modbus::ModbusMasterDataSource::IpcPipe { path } => {
            if path.is_empty() {
                return Ok(()); // Allow empty path, will use placeholder
            }
            // For IPC, we don't validate the path exists yet
            // It will be created or connected when starting
            Ok(())
        }
        types::modbus::ModbusMasterDataSource::PortForwarding { source_port } => {
            if source_port.is_empty() {
                return Ok(()); // Allow empty port, will use placeholder
            }
            // Validate that source_port is not the same as current port
            // This will be done at runtime validation
            Ok(())
        }
    }
}

/// Validate URL format
fn validate_url(url: &str, expected_scheme: &str) -> Result<(), String> {
    // Basic URL validation - check if it looks like a valid URL
    if let Ok(parsed) = url::Url::parse(url) {
        // Check if scheme matches expected
        if parsed.scheme() == expected_scheme || parsed.scheme() == format!("{}s", expected_scheme)
        {
            Ok(())
        } else {
            let err_msg = lang().protocol.modbus.err_invalid_url.replace("{}", url);
            Err(err_msg)
        }
    } else {
        let err_msg = lang().protocol.modbus.err_invalid_url.replace("{}", url);
        Err(err_msg)
    }
}
