Add all of the decoding functions.
use crate::instruction::Instruction;
use crate::parser::utilities::{read_u16_le, read_u32_le, read_i8, read_i16_le, read_i32_le};
use colored::*;

const REG8: [&str; 8] = ["AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH"];
const REG16: [&str; 8] = ["AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI"];
const REG32: [&str; 8] = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"];

pub fn disassemble(data: &[u8]) -> Result<Vec<Instruction>, String> {
    let mut instructions = Vec::new();
    let mut offset = 0;

    while offset < data.len() {
        let (instruction, size) = decode_instruction(data, offset)?;
        instructions.push(instruction);
        offset += size;
    }

    Ok(instructions)
}

fn decode_instruction(data: &[u8], offset: usize) -> Result<(Instruction, usize), String> {
    if offset >= data.len() {
        return Err("Unexpected end of data".to_string());
    }

    let mut prefix = 0;
    let mut current_offset = offset;

    // Handle prefixes
    while current_offset < data.len() {
        match data[current_offset] {
            0x66 => prefix |= 1, // Operand size override
            0x67 => prefix |= 2, // Address size override
            0xF0 => prefix |= 4, // LOCK prefix
            0xF2 => prefix |= 8, // REPNE/REPNZ prefix
            0xF3 => prefix |= 16, // REP/REPE/REPZ prefix
            _ => break,
        }
        current_offset += 1;
    }

    if current_offset >= data.len() {
        return Err("Unexpected end of data after prefixes".to_string());
    }

    let opcode = data[current_offset];
    let (mnemonic, operands, size) = match opcode {
        0x00..=0x03 => decode_add(data, current_offset, prefix)?,
        0x04 | 0x05 => decode_add_al_ax_eax(data, current_offset, prefix)?,
        0x08..=0x0B => decode_or(data, current_offset, prefix)?,
        0x0C | 0x0D => decode_or_al_ax_eax(data, current_offset, prefix)?,
        0x10..=0x13 => decode_adc(data, current_offset, prefix)?,
        0x14 | 0x15 => decode_adc_al_ax_eax(data, current_offset, prefix)?,
        0x20..=0x23 => decode_and(data, current_offset, prefix)?,
        0x24 | 0x25 => decode_and_al_ax_eax(data, current_offset, prefix)?,
        0x28..=0x2B => decode_sub(data, current_offset, prefix)?,
        0x2C | 0x2D => decode_sub_al_ax_eax(data, current_offset, prefix)?,
        0x30..=0x33 => decode_xor(data, current_offset, prefix)?,
        0x34 | 0x35 => decode_xor_al_ax_eax(data, current_offset, prefix)?,
        0x38..=0x3B => decode_cmp(data, current_offset, prefix)?,
        0x3C | 0x3D => decode_cmp_al_ax_eax(data, current_offset, prefix)?,
        0x40..=0x47 => decode_inc_reg(data, current_offset, prefix)?,
        0x48..=0x4F => decode_dec_reg(data, current_offset, prefix)?,
        0x50..=0x57 => decode_push_reg(data, current_offset, prefix)?,
        0x58..=0x5F => decode_pop_reg(data, current_offset, prefix)?,
        0x68 => decode_push_imm(data, current_offset, prefix)?,
        0x6A => decode_push_imm8(data, current_offset)?,
        0x70..=0x7F => decode_jcc_short(data, current_offset)?,
        0x80..=0x83 => decode_group1(data, current_offset, prefix)?,
        0x84 | 0x85 => decode_test(data, current_offset, prefix)?,
        0x86 | 0x87 => decode_xchg(data, current_offset, prefix)?,
        0x88..=0x8B => decode_mov(data, current_offset, prefix)?,
        0x8D => decode_lea(data, current_offset, prefix)?,
        0x8F => decode_pop_rm(data, current_offset, prefix)?,
        0x90 => ("NOP".to_string(), vec![], 1),
        0x91..=0x97 => decode_xchg_eax_reg(data, current_offset)?,
        0xB0..=0xB7 => decode_mov_reg8_imm8(data, current_offset)?,
        0xB8..=0xBF => decode_mov_reg_imm(data, current_offset, prefix)?,
        0xC3 => ("RET".to_string(), vec![], 1),
        0xC6 | 0xC7 => decode_mov_rm_imm(data, current_offset, prefix)?,
        0xE8 => decode_call_near(data, current_offset)?,
        0xE9 => decode_jmp_near(data, current_offset)?,
        0xEB => decode_jmp_short(data, current_offset)?,
        0xF6 | 0xF7 => decode_group3(data, current_offset, prefix)?,
        0xFF => decode_group5(data, current_offset, prefix)?,
        _ => (format!("DB 0x{:02X}", opcode), vec![], 1),
    };

    let instruction = Instruction {
        opcode,
        mnemonic,
        operands,
        bytes: data[offset..current_offset + size].to_vec(),
        address: offset,
    };

    Ok((instruction, current_offset - offset + size))
}

// Implementation of ADD instructions
fn decode_add(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "ADD".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x00 | 0x01 | 0x02 | 0x03 => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported ADD opcode: 0x{:02X}", opcode)),
    }
}

fn decode_add_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "ADD".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x04 => { // ADD AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for ADD AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x05 => { // ADD AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for ADD AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for ADD EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported ADD AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of OR instructions
fn decode_or(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "OR".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x08..=0x0B => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported OR opcode: 0x{:02X}", opcode)),
    }
}

fn decode_or_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "OR".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x0C => { // OR AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for OR AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x0D => { // OR AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for OR AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for OR EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported OR AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of ADC instructions
fn decode_adc(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "ADC".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x10..=0x13 => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported ADC opcode: 0x{:02X}", opcode)),
    }
}

fn decode_adc_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "ADC".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x14 => { // ADC AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for ADC AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x15 => { // ADC AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for ADC AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for ADC EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported ADC AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of AND instructions
fn decode_and(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize), String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "AND".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x20..=0x23 => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported AND opcode: 0x{:02X}", opcode)),
    }
}

fn decode_and_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "AND".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x24 => { // AND AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for AND AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x25 => { // AND AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for AND AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for AND EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported AND AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of SUB instructions
fn decode_sub(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "SUB".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x28..=0x2B => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported SUB opcode: 0x{:02X}", opcode)),
    }
}

fn decode_sub_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "SUB".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x2C => { // SUB AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for SUB AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x2D => { // SUB AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for SUB AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for SUB EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported SUB AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of XOR instructions
fn decode_xor(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "XOR".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x30..=0x33 => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported XOR opcode: 0x{:02X}", opcode)),
    }
}

fn decode_xor_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "XOR".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x34 => { // XOR AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for XOR AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x35 => { // XOR AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for XOR AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for XOR EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported XOR AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of CMP instructions
fn decode_cmp(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let mnemonic = "CMP".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x38..=0x3B => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported CMP opcode: 0x{:02X}", opcode)),
    }
}

fn decode_cmp_al_ax_eax(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "CMP".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x3C => { // CMP AL, imm8
            if offset + 1 >= data.len() {
                return Err("Unexpected end of data for CMP AL, imm8".to_string());
            }
            let imm8 = data[offset + 1];
            operands.push(REG8[0].to_string());
            operands.push(format!("0x{:02X}", imm8));
            size += 1;
        },
        0x3D => { // CMP AX/EAX, imm16/imm32
            let imm = if operand_size == 16 {
                if offset + 2 >= data.len() {
                    return Err("Unexpected end of data for CMP AX, imm16".to_string());
                }
                let imm16 = read_u16_le(data, offset + 1).unwrap();
                size += 2;
                imm16.to_string()
            } else {
                if offset + 4 >= data.len() {
                    return Err("Unexpected end of data for CMP EAX, imm32".to_string());
                }
                let imm32 = read_u32_le(data, offset + 1).unwrap();
                size += 4;
                imm32.to_string()
            };
            let reg = if operand_size == 16 { REG16[0] } else { REG32[0] };
            operands.push(reg.to_string());
            operands.push(format!("0x{}", imm));
        },
        _ => return Err(format!("Unsupported CMP AL/AX/EAX opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of INC instructions for registers
fn decode_inc_reg(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg = REG32[(opcode - 0x40) as usize].to_string();
    let mnemonic = "INC".to_string();
    let operands = vec![reg];
    Ok((mnemonic, operands, 1))
}

// Implementation of DEC instructions for registers
fn decode_dec_reg(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg = REG32[(opcode - 0x48) as usize].to_string();
    let mnemonic = "DEC".to_string();
    let operands = vec![reg];
    Ok((mnemonic, operands, 1))
}

// Implementation of PUSH instructions for registers
fn decode_push_reg(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg = REG32[(opcode - 0x50) as usize].to_string();
    let mnemonic = "PUSH".to_string();
    let operands = vec![reg];
    Ok((mnemonic, operands, 1))
}

// Implementation of POP instructions for registers
fn decode_pop_reg(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg = REG32[(opcode - 0x58) as usize].to_string();
    let mnemonic = "POP".to_string();
    let operands = vec![reg];
    Ok((mnemonic, operands, 1))
}

// Implementation of PUSH immediate
fn decode_push_imm(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let mnemonic = "PUSH".to_string();
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mut size = 1;
    let imm = if operand_size == 16 {
        if offset + 1 + 2 > data.len() {
            return Err("Unexpected end of data for PUSH imm16".to_string());
        }
        let imm16 = read_u16_le(data, offset + 1).unwrap().to_string();
        size += 2;
        imm16
    } else {
        if offset + 1 + 4 > data.len() {
            return Err("Unexpected end of data for PUSH imm32".to_string());
        }
        let imm32 = read_u32_le(data, offset + 1).unwrap().to_string();
        size += 4;
        imm32
    };
    let operands = vec![format!("0x{}", imm)];
    Ok((mnemonic, operands, size))
}

// Implementation of PUSH immediate 8-bit
fn decode_push_imm8(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let mnemonic = "PUSH".to_string();
    if offset + 1 >= data.len() {
        return Err("Unexpected end of data for PUSH imm8".to_string());
    }
    let imm8 = data[offset + 1];
    let operands = vec![format!("0x{:02X}", imm8)];
    Ok((mnemonic, operands, 2))
}

// Implementation of JCC short (conditional jumps)
fn decode_jcc_short(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let condition = match opcode {
        0x70 => "JO",
        0x71 => "JNO",
        0x72 => "JB",
        0x73 => "JNB",
        0x74 => "JE",
        0x75 => "JNE",
        0x76 => "JBE",
        0x77 => "JA",
        0x78 => "JS",
        0x79 => "JNS",
        0x7A => "JP",
        0x7B => "JNP",
        0x7C => "JL",
        0x7D => "JNL",
        0x7E => "JLE",
        0x7F => "JNG",
        _ => return Err(format!("Unsupported JCC short opcode: 0x{:02X}", opcode)),
    };
    if offset + 1 >= data.len() {
        return Err("Unexpected end of data for JCC short".to_string());
    }
    let disp8 = data[offset + 1] as i8;
    let target = offset.wrapping_add(2).wrapping_add(disp8 as usize);
    let operands = vec![format!("0x{:04X}", target)];
    Ok((condition.to_string(), operands, 2))
}

// Implementation of GROUP1 instructions (ADD, OR, ADC, SBB, AND, SUB, XOR, CMP with immediate)
fn decode_group1(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    if offset + 1 >= data.len() {
        return Err("Unexpected end of data for GROUP1".to_string());
    }
    let modrm = data[offset + 1];
    let reg = (modrm >> 3) & 0x07;
    let mut mnemonic = String::new();
    match reg {
        0 => mnemonic = "ADD".to_string(),
        1 => mnemonic = "OR".to_string(),
        2 => mnemonic = "ADC".to_string(),
        3 => mnemonic = "SBB".to_string(),
        4 => mnemonic = "AND".to_string(),
        5 => mnemonic = "SUB".to_string(),
        6 => mnemonic = "XOR".to_string(),
        7 => mnemonic = "CMP".to_string(),
        _ => return Err(format!("Unsupported GROUP1 reg field: {}", reg)),
    }
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mut current_offset = offset + 2;
    let mut operands = Vec::new();
    let mut size = 2;
    let imm = if (opcode == 0x80 || opcode == 0x81 || opcode == 0x83) && ((modrm & 0xC0) != 0xC0) {
        // r/m operand with immediate
        // For simplicity, handle only immediate to register/memory
        if opcode == 0x80 || opcode == 0x82 {
            // Immediate byte
            if current_offset >= data.len() {
                return Err("Unexpected end of data for GROUP1 imm8".to_string());
            }
            let imm8 = data[current_offset];
            current_offset += 1;
            size += 1;
            format!("0x{:02X}", imm8)
        } else if opcode == 0x81 {
            // Immediate word/dword
            if operand_size == 16 {
                if current_offset + 1 >= data.len() {
                    return Err("Unexpected end of data for GROUP1 imm16".to_string());
                }
                let imm16 = read_u16_le(data, current_offset).unwrap();
                current_offset += 2;
                size += 2;
                format!("0x{:04X}", imm16)
            } else {
                if current_offset + 3 >= data.len() {
                    return Err("Unexpected end of data for GROUP1 imm32".to_string());
                }
                let imm32 = read_u32_le(data, current_offset).unwrap();
                current_offset += 4;
                size += 4;
                format!("0x{:08X}", imm32)
            }
        } else { // 0x83 sign-extended immediate byte
            if current_offset >= data.len() {
                return Err("Unexpected end of data for GROUP1 imm8".to_string());
            }
            let imm8 = data[current_offset] as i8;
            current_offset += 1;
            size += 1;
            format!("0x{:02X}", imm8)
        }
    } else {
        // Immediate to register
        if opcode == 0x80 || opcode == 0x82 {
            // Immediate byte
            if current_offset >= data.len() {
                return Err("Unexpected end of data for GROUP1 imm8".to_string());
            }
            let imm8 = data[current_offset];
            current_offset += 1;
            size += 1;
            format!("0x{:02X}", imm8)
        } else if opcode == 0x81 {
            // Immediate word/dword
            if operand_size == 16 {
                if current_offset + 1 >= data.len() {
                    return Err("Unexpected end of data for GROUP1 imm16".to_string());
                }
                let imm16 = read_u16_le(data, current_offset).unwrap();
                current_offset += 2;
                size += 2;
                format!("0x{:04X}", imm16)
            } else {
                if current_offset + 3 >= data.len() {
                    return Err("Unexpected end of data for GROUP1 imm32".to_string());
                }
                let imm32 = read_u32_le(data, current_offset).unwrap();
                current_offset += 4;
                size += 4;
                format!("0x{:08X}", imm32)
            }
        } else { // 0x83 sign-extended immediate byte
            if current_offset >= data.len() {
                return Err("Unexpected end of data for GROUP1 imm8".to_string());
            }
            let imm8 = data[current_offset] as i8;
            current_offset += 1;
            size += 1;
            format!("0x{:02X}", imm8)
        }
    };

    // For simplicity, operands are not fully decoded here
    operands.push(imm);
    Ok((mnemonic, operands, size))
}

// Implementation of TEST instructions
fn decode_test(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "TEST".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    match opcode {
        0x84 | 0x85 => {
            let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            current_offset += modrm_size;
            size += modrm_size;
            operands.push(dst);
            operands.push(src);
        },
        _ => return Err(format!("Unsupported TEST opcode: 0x{:02X}", opcode)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of XCHG instructions
fn decode_xchg(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;

    let mnemonic = "XCHG".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x86 | 0x87 => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            operands.push(src);
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported XCHG opcode: 0x{:02X}", opcode)),
    }
}

// Implementation of MOV instructions
fn decode_mov(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;
    let mnemonic = "MOV".to_string();
    let mut operands = Vec::new();

    match opcode {
        0x88..=0x8B => {
            let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
            match opcode {
                0x88 | 0x89 => { // MOV r/m8/16/32, r8/16/32
                    operands.push(dst);
                    operands.push(src);
                },
                0x8A | 0x8B => { // MOV r8/16/32, r/m8/16/32
                    operands.push(dst);
                    operands.push(src);
                },
                _ => {},
            }
            Ok((mnemonic, operands, size))
        },
        _ => Err(format!("Unsupported MOV opcode: 0x{:02X}", opcode)),
    }
}

// Implementation of LEA instruction
fn decode_lea(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;
    let mnemonic = "LEA".to_string();
    let mut operands = Vec::new();

    if current_offset >= data.len() {
        return Err("Unexpected end of data for LEA".to_string());
    }

    let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
    current_offset += size;
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let reg_name = if operand_size == 16 { REG16 } else { REG32 };
    let dst_reg = dst.clone(); // Destination is a register
    operands.push(dst_reg);
    operands.push(src);
    Ok((mnemonic, operands, size))
}

// Implementation of POP r/m16/32
fn decode_pop_rm(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;
    let mnemonic = "POP".to_string();
    let mut operands = Vec::new();

    let (src, dst, size) = decode_modrm(data, current_offset, prefix)?;
    operands.push(src);
    operands.push(dst);
    Ok((mnemonic, operands, size))
}

// Implementation of XCHG EAX, reg
fn decode_xchg_eax_reg(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg = REG32[(opcode - 0x90) as usize].to_string();
    let mnemonic = "XCHG".to_string();
    let operands = vec!["EAX".to_string(), reg];
    Ok((mnemonic, operands, 1))
}

// Implementation of MOV reg8, imm8
fn decode_mov_reg8_imm8(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg_index = (opcode - 0xB0) as usize;
    if offset + 1 >= data.len() {
        return Err("Unexpected end of data for MOV reg8, imm8".to_string());
    }
    let imm8 = data[offset + 1];
    let mnemonic = "MOV".to_string();
    let operands = vec![REG8[reg_index].to_string(), format!("0x{:02X}", imm8)];
    Ok((mnemonic, operands, 2))
}

// Implementation of MOV reg16/32, imm16/32
fn decode_mov_reg_imm(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let reg_index = (opcode - 0xB8) as usize;
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mnemonic = "MOV".to_string();
    let mut operands = Vec::new();
    let mut size = 1;

    let imm = if operand_size == 16 {
        if offset + 1 + 2 > data.len() {
            return Err("Unexpected end of data for MOV reg16, imm16".to_string());
        }
        let imm16 = read_u16_le(data, offset + 1).unwrap();
        size += 2;
        format!("0x{:04X}", imm16)
    } else {
        if offset + 1 + 4 > data.len() {
            return Err("Unexpected end of data for MOV reg32, imm32".to_string());
        }
        let imm32 = read_u32_le(data, offset + 1).unwrap();
        size += 4;
        format!("0x{:08X}", imm32)
    };

    let reg = if operand_size == 16 { REG16[reg_index] } else { REG32[reg_index] };
    operands.push(reg.to_string());
    operands.push(format!("0x{}", imm));
    Ok((mnemonic, operands, size))
}

// Implementation of MOV r/m16/32, imm16/32 or imm8
fn decode_mov_rm_imm(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;
    let mut mnemonic = "MOV".to_string();
    let mut operands = Vec::new();
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };
    let mut size = 1;

    if opcode == 0xC6 {
        // MOV r/m8, imm8
        let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
        current_offset += modrm_size;
        size += modrm_size;

        if current_offset >= data.len() {
            return Err("Unexpected end of data for MOV r/m8, imm8".to_string());
        }
        let imm8 = data[current_offset];
        current_offset += 1;
        size += 1;

        operands.push(dst);
        operands.push(format!("0x{:02X}", imm8));
    } else if opcode == 0xC7 {
        // MOV r/m16/32, imm16/32
        let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
        current_offset += modrm_size;
        size += modrm_size;

        let imm = if operand_size == 16 {
            if current_offset + 1 >= data.len() {
                return Err("Unexpected end of data for MOV r/m16, imm16".to_string());
            }
            let imm16 = read_u16_le(data, current_offset).unwrap();
            current_offset += 2;
            size += 2;
            format!("0x{:04X}", imm16)
        } else {
            if current_offset + 3 >= data.len() {
                return Err("Unexpected end of data for MOV r/m32, imm32".to_string());
            }
            let imm32 = read_u32_le(data, current_offset).unwrap();
            current_offset += 4;
            size += 4;
            format!("0x{:08X}", imm32)
        };

        operands.push(dst);
        operands.push(format!("0x{}", imm));
    } else {
        return Err(format!("Unsupported MOV r/m, imm opcode: 0x{:02X}", opcode));
    }

    Ok((mnemonic, operands, size))
}

// Implementation of CALL near
fn decode_call_near(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let mnemonic = "CALL".to_string();
    if offset + 4 >= data.len() {
        return Err("Unexpected end of data for CALL near".to_string());
    }
    let rel32 = read_i32_le(data, offset + 1).unwrap();
    let target = offset.wrapping_add(5).wrapping_add(rel32 as usize);
    let operands = vec![format!("0x{:04X}", target)];
    Ok((mnemonic, operands, 5))
}

// Implementation of JMP near
fn decode_jmp_near(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let mnemonic = "JMP".to_string();
    if offset + 4 >= data.len() {
        return Err("Unexpected end of data for JMP near".to_string());
    }
    let rel32 = read_i32_le(data, offset + 1).unwrap();
    let target = offset.wrapping_add(5).wrapping_add(rel32 as usize);
    let operands = vec![format!("0x{:04X}", target)];
    Ok((mnemonic, operands, 5))
}

// Implementation of JMP short
fn decode_jmp_short(data: &[u8], offset: usize) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    if opcode != 0xEB {
        return Err(format!("Unsupported JMP short opcode: 0x{:02X}", opcode));
    }
    if offset + 1 >= data.len() {
        return Err("Unexpected end of data for JMP short".to_string());
    }
    let disp8 = data[offset + 1] as i8;
    let target = offset.wrapping_add(2).wrapping_add(disp8 as usize);
    let mnemonic = "JMP".to_string();
    let operands = vec![format!("0x{:04X}", target)];
    Ok((mnemonic, operands, 2))
}

// Implementation of GROUP3 instructions (TEST, NOT, NEG, MUL, etc.)
fn decode_group3(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;
    let mut mnemonic = String::new();
    let mut operands = Vec::new();
    let mut size = 1;

    if current_offset >= data.len() {
        return Err("Unexpected end of data for GROUP3".to_string());
    }

    let modrm = data[current_offset];
    let reg = (modrm >> 3) & 0x07;
    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    match reg {
        0 => { // TEST r/m8, imm8
            mnemonic = "TEST".to_string();
            let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            current_offset += modrm_size;
            size += modrm_size;
            if current_offset >= data.len() {
                return Err("Unexpected end of data for TEST in GROUP3".to_string());
            }
            let imm8 = data[current_offset];
            current_offset += 1;
            size += 1;
            operands.push(dst);
            operands.push(format!("0x{:02X}", imm8));
        },
        3 => { // NEG r/m16/32
            mnemonic = "NEG".to_string();
            let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            size += modrm_size;
        },
        2 => { // NOT r/m16/32
            mnemonic = "NOT".to_string();
            let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            size += modrm_size;
        },
        4 => { // MUL r/m8
            mnemonic = "MUL".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        5 => { // IMUL r/m8
            mnemonic = "IMUL".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        6 => { // DIV r/m8
            mnemonic = "DIV".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        7 => { // IDIV r/m8
            mnemonic = "IDIV".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        _ => return Err(format!("Unsupported GROUP3 reg field: {}", reg)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of GROUP5 instructions (INC, DEC, CALL, JMP, PUSH with r/m16/32)
fn decode_group5(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    let opcode = data[offset];
    let mut current_offset = offset + 1;
    let mut mnemonic = String::new();
    let mut operands = Vec::new();
    let mut size = 1;

    if current_offset >= data.len() {
        return Err("Unexpected end of data for GROUP5".to_string());
    }

    let modrm = data[current_offset];
    let reg = (modrm >> 3) & 0x07;

    match reg {
        0 => { // INC r/m16/32
            mnemonic = "INC".to_string();
            let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            size += modrm_size;
        },
        1 => { // DEC r/m16/32
            mnemonic = "DEC".to_string();
            let (src, dst, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(dst);
            size += modrm_size;
        },
        2 => { // CALL r/m16/32
            mnemonic = "CALL".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        4 => { // JMP r/m16/32
            mnemonic = "JMP".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        6 => { // PUSH r/m16/32
            mnemonic = "PUSH".to_string();
            let (src, _, modrm_size) = decode_modrm(data, current_offset, prefix)?;
            operands.push(src);
            size += modrm_size;
        },
        _ => return Err(format!("Unsupported GROUP5 reg field: {}", reg)),
    }

    Ok((mnemonic, operands, size))
}

// Implementation of LEA instruction
fn decode_lea(data: &[u8], offset: usize, prefix: u8) -> Result<(String, Vec<String>, usize>, String>, String> {
    // This function was already implemented above
    unimplemented!()
}

// Helper function to decode ModRM byte
fn decode_modrm(data: &[u8], offset: usize, prefix: u8) -> Result<(String, String, usize), String> {
    if offset >= data.len() {
        return Err("Unexpected end of data while decoding ModRM".to_string());
    }

    let modrm = data[offset];
    let mod_bits = modrm >> 6;
    let reg = (modrm >> 3) & 0x07;
    let rm = modrm & 0x07;

    let operand_size = if (prefix & 1) != 0 { 16 } else { 32 };

    let (src, dst, size) = match mod_bits {
        0b00 => {
            if rm == 0b100 {
                decode_sib(data, offset + 1, prefix)?
            } else if rm == 0b101 {
                if operand_size == 16 {
                    let disp16 = read_i16_le(data, offset + 1).ok_or("Unexpected end of data")?;
                    (format!("[0x{:04X}]", disp16 as u16), REG16[reg as usize].to_string(), 3)
                } else {
                    let disp32 = read_i32_le(data, offset + 1).ok_or("Unexpected end of data")?;
                    (format!("[0x{:08X}]", disp32), REG32[reg as usize].to_string(), 5)
                }
            } else {
                (format!("[{}]", REG32[rm as usize]), REG32[reg as usize].to_string(), 1)
            }
        },
        0b01 => {
            let disp8 = read_i8(data, offset + 1).ok_or("Unexpected end of data")?;
            if rm == 0b100 {
                let (base, index, scale) = decode_sib(data, offset + 1, prefix)?;
                let addr = if (prefix & 2) != 0 { // Address size override
                    format!("[{} + {} * {} + {}]", base, index, scale, disp8)
                } else {
                    format!("[{} + {} * {} + {}]", base, index, scale, disp8)
                };
                (addr, REG32[reg as usize].to_string(), 2)
            } else {
                (format!("[{} + {}]", REG32[rm as usize], disp8), REG32[reg as usize].to_string(), 2)
            }
        },
        0b10 => {
            let disp = if operand_size == 16 {
                let disp16 = read_i16_le(data, offset + 1).ok_or("Unexpected end of data")?;
                disp16 as i32
            } else {
                read_i32_le(data, offset + 1).ok_or("Unexpected end of data")?
            };
            if rm == 0b100 {
                let (base, index, scale) = decode_sib(data, offset + 1, prefix)?;
                if operand_size == 16 {
                    (format!("[{} + {} * {} + {}]", base, index, scale, disp), REG16[reg as usize].to_string(), if operand_size == 16 { 4 } else { 6 })
                } else {
                    (format!("[{} + {} * {} + {}]", base, index, scale, disp), REG32[reg as usize].to_string(), 6)
                }
            } else {
                if operand_size == 16 {
                    (format!("[{} + {}]", REG16[rm as usize], disp), REG16[reg as usize].to_string(), 3)
                } else {
                    (format!("[{} + {}]", REG32[rm as usize], disp), REG32[reg as usize].to_string(), 5)
                }
            }
        },
        0b11 => {
            if operand_size == 16 {
                (REG16[rm as usize].to_string(), REG16[reg as usize].to_string(), 1)
            } else {
                (REG32[rm as usize].to_string(), REG32[reg as usize].to_string(), 1)
            }
        },
        _ => unreachable!(),
    };

    Ok((src, dst, size))
}

// Helper function to decode SIB byte
fn decode_sib(data: &[u8], offset: usize, prefix: u8) -> Result<(String, String, u8), String> {
    if offset >= data.len() {
        return Err("Unexpected end of data while decoding SIB".to_string());
    }

    let sib = data[offset];
    let scale = 1 << ((sib >> 6) & 0x03);
    let index = (sib >> 3) & 0x07;
    let base = sib & 0x07;

    let base_reg = if base == 0b101 {
        // Special case when mod bits are 00 and base is 101
        if (prefix & 2) != 0 { // Address size override
            "BP".to_string()
        } else {
            "EBP".to_string()
        }
    } else {
        REG32[base as usize].to_string()
    };

    let index_reg = if index == 0b100 {
        "".to_string() // No index
    } else {
        REG32[index as usize].to_string()
    };

    Ok((base_reg, index_reg, scale))
}

// Function to format the disassembled instructions
pub fn format_disassembly(instructions: &[Instruction]) -> String {
    instructions
        .iter()
        .map(|instr| {
            format!(
                "{}: {} {}{}",
                format!("{:04X}", instr.address).yellow(),
                instr.bytes.iter().map(|b| format!("{:02X}", b)).collect::<Vec<String>>().join(" ").cyan(),
                instr.mnemonic.green(),
                if instr.operands.is_empty() {
                    String::new()
                } else {
                    format!(" {}", instr.operands.join(", ").white())
                }
            )
        })
        .collect::<Vec<String>>()
        .join("\n")
}

Make a comprehensive adding of these functions.
This is instruction.rs if you need it.
use std::fmt;

#[derive(Debug, Clone)]
pub struct Instruction {
    pub opcode: u8,
    pub mnemonic: String,
    pub operands: Vec<String>,
    pub bytes: Vec<u8>,
    pub address: usize,
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{:04X}: {:10} {}",
            self.address,
            self.bytes.iter().map(|b| format!("{:02X}", b)).collect::<Vec<String>>().join(" "),
            self.mnemonic
        )?;
        if !self.operands.is_empty() {
            write!(f, " {}", self.operands.join(", "))?;
        }
        Ok(())
    }
}