use irc::client::prelude::*;

/// Escape HTML special characters
fn escape_html(s: &str) -> String {
    s.replace('&', "&amp;")
        .replace('<', "&lt;")
        .replace('>', "&gt;")
        .replace('"', "&quot;")
        .replace('\'', "&#39;")
}

/// Format an IRC message with HTML colors and beautification
pub fn format_message(message: &Message) -> String {
    // Extract prefix (server or user)
    let prefix_str = match &message.prefix {
        Some(Prefix::ServerName(server)) => {
            format!("<span style='color: #5ddfff;'>{}</span>", escape_html(server))
        },
        Some(Prefix::Nickname(nick, user, host)) => {
            if !host.is_empty() {
                format!("<span style='color: #5af78e;'>{}</span><span style='color: #666;'>@{}</span>", 
                    escape_html(nick), escape_html(host))
            } else if !user.is_empty() {
                format!("<span style='color: #5af78e;'>{}</span><span style='color: #666;'>@{}</span>", 
                    escape_html(nick), escape_html(user))
            } else {
                format!("<span style='color: #5af78e;'>{}</span>", escape_html(nick))
            }
        },
        None => String::new(),
    };
    
    // Format based on command type
    match &message.command {
        Command::NOTICE(target, text) => {
            format!("<span style='color: #666;'><span style='color: #ffd700;'>[NOTICE]</span> </span>{}<span style='color: #666;'> → </span><span style='color: #666;'>{}</span><span style='color: #666;'>: </span><span style='color: #ffd700;'>{}</span>",
                prefix_str,
                escape_html(target),
                escape_html(text))
        },
        Command::PRIVMSG(target, text) => {
            format!("{}<span style='color: #666;'> → </span><span style='color: #666;'>{}</span><span style='color: #666;'>: </span><span style='color: #fff;'>{}</span>",
                prefix_str,
                escape_html(target),
                escape_html(text))
        },
        Command::JOIN(channel, keys, _) => {
            let keys_str = if let Some(k) = keys {
                format!(" <span style='color: #666;'>(key: {})</span>", escape_html(k))
            } else {
                String::new()
            };
            format!("{}<span style='color: #5af78e;'> joined </span><span style='color: #5ddfff;'>{}</span>{}",
                prefix_str,
                escape_html(channel),
                keys_str)
        },
        Command::PART(channel, msg) => {
            let msg_str = if let Some(m) = msg {
                format!(" <span style='color: #666;'>({})</span>", escape_html(m))
            } else {
                String::new()
            };
            format!("{}<span style='color: #ff5f87;'> left </span><span style='color: #5ddfff;'>{}</span>{}",
                prefix_str,
                escape_html(channel),
                msg_str)
        },
        Command::QUIT(msg) => {
            let msg_str = if let Some(m) = msg {
                format!(" <span style='color: #666;'>({})</span>", escape_html(m))
            } else {
                String::new()
            };
            format!("{}<span style='color: #ff5f87;'> quit</span>{}",
                prefix_str,
                msg_str)
        },
        Command::NICK(new_nick) => {
            format!("{}<span style='color: #5af78e;'> is now known as </span><span style='color: #5af78e;'>{}</span>",
                prefix_str,
                escape_html(new_nick))
        },
        Command::TOPIC(channel, topic) => {
            if let Some(t) = topic {
                format!("{}<span style='color: #5ddfff;'>Topic for </span><span style='color: #5ddfff;'>{}</span><span style='color: #666;'>: </span><span style='color: #ffd700;'>{}</span>",
                    prefix_str,
                    escape_html(channel),
                    escape_html(t))
            } else {
                format!("{}<span style='color: #5ddfff;'>Topic for </span><span style='color: #5ddfff;'>{}</span><span style='color: #666;'> cleared</span>",
                    prefix_str,
                    escape_html(channel))
            }
        },
        Command::KICK(channel, user, msg) => {
            let msg_str = if let Some(m) = msg {
                format!(" <span style='color: #666;'>({})</span>", escape_html(m))
            } else {
                String::new()
            };
            format!("{}<span style='color: #ff5f87;'> kicked </span><span style='color: #ff5f87;'>{}</span><span style='color: #666;'> from </span><span style='color: #5ddfff;'>{}</span>{}",
                prefix_str,
                escape_html(user),
                escape_html(channel),
                msg_str)
        },
        Command::Response(code, params) => {
            // Special handling for RPL_NAMREPLY (353) - format user list nicely
            if let Response::RPL_NAMREPLY = code {
                if params.len() >= 4 {
                    let channel = &params[2];
                    let users_str = &params[3];
                    // Split users and format them
                    let users: Vec<&str> = users_str.split_whitespace().collect();
                    let formatted_users: Vec<String> = users.iter()
                        .map(|u| {
                            // Check for channel prefixes (@ for ops, + for voiced)
                            if u.starts_with('@') {
                                format!("<span style='color: #ff5f87; font-weight: bold;'>{}</span>", escape_html(u))
                            } else if u.starts_with('+') {
                                format!("<span style='color: #5af78e;'>{}</span>", escape_html(u))
                            } else {
                                format!("<span style='color: #fff;'>{}</span>", escape_html(u))
                            }
                        })
                        .collect();
                    
                    return format!("{}<span style='color: #666;'>[</span><span style='color: #5ddfff;'>NAMES</span><span style='color: #666;'>] </span><span style='color: #5ddfff;'>{}</span><span style='color: #666;'>: </span>{}",
                        prefix_str,
                        escape_html(channel),
                        formatted_users.join(" "));
                }
            }
            
            // Special handling for RPL_ENDOFNAMES (366)
            if let Response::RPL_ENDOFNAMES = code {
                if params.len() >= 2 {
                    let channel = &params[1];
                    return format!("{}<span style='color: #666;'>[</span><span style='color: #5ddfff;'>ENDOFNAMES</span><span style='color: #666;'>] </span><span style='color: #5ddfff;'>{}</span><span style='color: #666;'>: End of /NAMES list.</span>",
                        prefix_str,
                        escape_html(channel));
                }
            }
            
            let code_str = format!("{:?}", code);
            let params_str = params.iter()
                .map(|p| format!("<span style='color: #fff;'>{}</span>", escape_html(p)))
                .collect::<Vec<_>>()
                .join(" ");
            format!("{}<span style='color: #666;'>[</span><span style='color: #5ddfff;'>{}</span><span style='color: #666;'>]</span> {}",
                prefix_str,
                escape_html(&code_str),
                params_str)
        },
        Command::PING(server1, server2) => {
            let servers = if let Some(s2) = server2 {
                format!("{}, {}", server1, s2)
            } else {
                server1.clone()
            };
            format!("<span style='color: #666;'><span style='color: #5af78e;'>[PING]</span> </span>{}",
                escape_html(&servers))
        },
        Command::PONG(server1, server2) => {
            let servers = if let Some(s2) = server2 {
                format!("{}, {}", server1, s2)
            } else {
                server1.clone()
            };
            format!("<span style='color: #666;'><span style='color: #5af78e;'>[PONG]</span> </span>{}",
                escape_html(&servers))
        },
        Command::INVITE(user, channel) => {
            format!("{}<span style='color: #ff87d7;'> invited </span><span style='color: #5af78e;'>{}</span><span style='color: #666;'> to </span><span style='color: #5ddfff;'>{}</span>",
                prefix_str,
                escape_html(user),
                escape_html(channel))
        },
        Command::Raw(code, params) => {
            let params_str = params.iter()
                .map(|p| format!("<span style='color: #666;'>{}</span>", escape_html(p)))
                .collect::<Vec<_>>()
                .join(" ");
            format!("{}<span style='color: #666;'>[RAW {}]</span> {}",
                prefix_str,
                code,
                params_str)
        },
        _ => {
            // Fallback for unhandled commands
            format!("{}<span style='color: #666;'>[{:?}]</span>",
                prefix_str,
                message.command)
        }
    }
}
