use crc::{Crc, CRC_16_MODBUS};
use serialport::SerialPort;
use std::io::{self, Read, Write};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;

pub fn get_default_settings(port_name: &str, baud_rate: u32) -> serialport::SerialPortBuilder {
    serialport::new(port_name, baud_rate)
        .data_bits(serialport::DataBits::Eight)
        .flow_control(serialport::FlowControl::None)
        .parity(serialport::Parity::None)
        .stop_bits(serialport::StopBits::One)
        .timeout(Duration::from_millis(100))
}

pub fn calculate_crc16(data: &[u8]) -> u16 {
    let crc = Crc::<u16>::new(&CRC_16_MODBUS);
    crc.checksum(data)
}

pub fn receive_data(port: &mut Box<dyn SerialPort>, running: Arc<AtomicBool>, pause_receiver: Arc<AtomicBool>) {
    let mut buffer: [u8; 1024] = [0; 1024];
    
    while running.load(Ordering::Relaxed) {
        // Если прием данных приостановлен, пропускаем итерацию
        if pause_receiver.load(Ordering::Relaxed) {
            std::thread::sleep(std::time::Duration::from_millis(10));
            continue;
        }
        
        match port.read(&mut buffer) {
            Ok(bytes_read) if bytes_read > 0 => {
                let received_data = &buffer[0..bytes_read];
                println!("📥 Получено (HEX): {}", format_hex_output(received_data));
                
                // Попытка интерпретировать как текст, если возможно
                if let Ok(text) = std::str::from_utf8(received_data) {
                    if text.chars().all(|c| c.is_ascii_graphic() || c.is_ascii_whitespace()) {
                        println!("📥 Получено (текст): {}", text);
                    }
                }
            }
            Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => {
                // Таймаут - это нормально, просто продолжаем
            }
            Err(e) => {
                if running.load(Ordering::Relaxed) {
                    println!("❌ Ошибка чтения из порта: {}", e);
                }
                break;
            }
            _ => {}
        }
    }
}

pub fn receive_data_with_pause(port: &mut Box<dyn SerialPort>, running: Arc<AtomicBool>, pause_receiver: Arc<AtomicBool>) {
    let mut buffer = [0; 1024];
    let mut data_buffer = Vec::new();

    while running.load(Ordering::Relaxed) {
        match port.read(&mut buffer) {
            Ok(t) => {
                if t == 0 {
                    continue;
                }
                
                // Only process and display data if not paused
                if !pause_receiver.load(Ordering::Relaxed) {
                    data_buffer.extend_from_slice(&buffer[..t]);
                    if let Some(data) = process_received_data(&mut data_buffer) {
                        println!("📥 Получены данные: {}", format_hex_output(&data));
                    }
                }
            }
            Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
            Err(e) => eprintln!("Ошибка чтения: {}", e),
        }
    }
}

fn process_received_data(buffer: &mut Vec<u8>) -> Option<Vec<u8>> {
    if buffer.is_empty() {
        return None;
    }
    
    // For now, just return the entire buffer as a single message
    let data = buffer.clone();
    buffer.clear();
    Some(data)
}

fn validate_hex_string(hex_string: &str) -> Result<Vec<u8>, &'static str> {
    let hex_string = hex_string.replace(" ", "");
    if !hex_string.chars().all(|c| c.is_ascii_hexdigit()) {
        return Err("неверный формат HEX данных");
    }
    hex::decode(&hex_string).map_err(|_| "неверный формат HEX данных")
}

pub fn format_hex_output(data: &[u8]) -> String {
    data.iter()
        .map(|b| format!("{:02X}", b))
        .collect::<Vec<String>>()
        .join(" ")
}

pub fn send_hex_data(port: &mut Box<dyn SerialPort>, hex_string: &str) {
    match validate_hex_string(hex_string) {
        Ok(data) => {
            // Получаем имя порта (если возможно)
            let port_name = port.name().unwrap_or_else(|| String::from("Неизвестный порт"));
            
            match port.write_all(&data) {
                Ok(_) => {
                    // Убираем вывод времени отправки
                    println!("📤 Отправлено в порт {} (HEX): {}",
                             port_name, format_hex_output(&data));
                }
                Err(e) => println!("❌ Ошибка при отправке данных: {}", e),
            }
        }
        Err(e) => println!("❌ Ошибка: {}", e),
    }
}

pub fn send_hex_data_with_crc(port: &mut Box<dyn SerialPort>, hex_string: &str) {
    match validate_hex_string(hex_string) {
        Ok(data) => {
            // Получаем имя порта (если возможно)
            let port_name = port.name().unwrap_or_else(|| String::from("Неизвестный порт"));
            
            let crc = calculate_crc16(&data);
            let mut final_data = data.clone();
            final_data.extend_from_slice(&crc.to_le_bytes());
            
            match port.write_all(&final_data) {
                Ok(_) => {
                    // Убираем вывод времени отправки
                    println!("📤 Отправлено в порт {} (HEX+CRC): {} | CRC: {:02X} {:02X}",
                             port_name, format_hex_output(&data),
                             crc & 0xFF, (crc >> 8) & 0xFF);
                }
                Err(e) => println!("❌ Ошибка: {}", e),
            }
        }
        Err(e) => println!("❌ Ошибка: {}", e),
    }
}

pub fn send_text_message(port: &mut Box<dyn SerialPort>, message: &str) {
    // Получаем имя порта (если возможно)
    let port_name = port.name().unwrap_or_else(|| String::from("Неизвестный порт"));
    
    let data = message.as_bytes();
    
    match port.write_all(data) {
        Ok(_) => {
            // Убираем вывод времени отправки
            println!("📤 Отправлено в порт {} (текст): {}", port_name, message);
        }
        Err(e) => println!("❌ Ошибка: {}", e),
    }
}

pub fn list_available_ports() -> Vec<serialport::SerialPortInfo> {
    match serialport::available_ports() {
        Ok(ports) => {
            if ports.is_empty() {
                println!("❌ Нет доступных последовательных портов!");
                return vec![];
            }

            println!("\n🔌 Доступные порты:");
            for (i, port) in ports.iter().enumerate() {
                println!("  {}. {}", i + 1, port.port_name);
            }
            ports
        }
        Err(e) => {
            println!("❌ Ошибка при получении списка портов: {}", e);
            vec![]
        }
    }
}

pub fn select_port() -> Option<String> {
    let ports = list_available_ports();
    if ports.is_empty() {
        return None;
    }

    loop {
        print!("\nВведите номер порта: ");
        io::stdout().flush().unwrap();

        let mut input = String::new();
        if io::stdin().read_line(&mut input).is_err() {
            println!("⚠️ Ошибка: введите число!");
            continue;
        }

        if let Ok(selected_index) = input.trim().parse::<usize>() {
            if selected_index > 0 && selected_index <= ports.len() {
                return Some(ports[selected_index - 1].port_name.clone());
            }
        }
        println!("⚠️ Ошибка: введите корректный номер порта!");
    }
}

#[allow(dead_code)]
pub fn process_request(request: &[u8]) -> Option<Vec<u8>> {
    match request {
        [0x01, 0x02, 0x03] => Some(vec![0x01, 0x0C]),
        [0x41] => Some(vec![0x20, 0x00]),
        [0xAA, 0xBB, 0xCC] => Some(vec![0xDD, 0xEE]),
        [0x01, b1, _b2] => Some(vec![0x01, b1 + 10]),
        _ => None,
    }
}

pub fn clear_screen() {
    #[cfg(target_os = "windows")]
    std::process::Command::new("cmd")
        .args(&["/C", "cls"])
        .status()
        .unwrap();
    #[cfg(not(target_os = "windows"))]
    std::process::Command::new("clear")
        .status()
        .unwrap();
} 