//! Chat window for the agent
//!
//! Provides a simple chat interface for communication between
//! the technician and the end user.

use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
use tracing::info;
#[cfg(not(windows))]
use tracing::warn;

#[cfg(windows)]
use windows::core::PCWSTR;
#[cfg(windows)]
use windows::Win32::UI::WindowsAndMessaging::*;

/// A chat message
#[derive(Debug, Clone)]
pub struct ChatMessage {
    pub id: String,
    pub sender: String,
    pub content: String,
    pub timestamp: i64,
}

/// Commands that can be sent to the chat window
// Show/Hide/Close are part of the chat control API but not yet driven by the session loop.
#[derive(Debug)]
pub enum ChatCommand {
    #[allow(dead_code)]
    Show,
    #[allow(dead_code)]
    Hide,
    AddMessage(ChatMessage),
    #[allow(dead_code)]
    Close,
}

/// Controller for the chat window
pub struct ChatController {
    command_tx: Sender<ChatCommand>,
    message_rx: Arc<Mutex<Receiver<ChatMessage>>>,
    _handle: thread::JoinHandle<()>,
}

impl ChatController {
    /// Create a new chat controller (spawns chat window thread)
    #[cfg(windows)]
    pub fn new() -> Option<Self> {
        let (command_tx, command_rx) = mpsc::channel::<ChatCommand>();
        let (message_tx, message_rx) = mpsc::channel::<ChatMessage>();

        let handle = thread::spawn(move || {
            run_chat_window(command_rx, message_tx);
        });

        Some(Self {
            command_tx,
            message_rx: Arc::new(Mutex::new(message_rx)),
            _handle: handle,
        })
    }

    #[cfg(not(windows))]
    pub fn new() -> Option<Self> {
        warn!("Chat window not supported on this platform");
        None
    }

    /// Show the chat window
    #[allow(dead_code)]
    pub fn show(&self) {
        let _ = self.command_tx.send(ChatCommand::Show);
    }

    /// Hide the chat window
    #[allow(dead_code)]
    pub fn hide(&self) {
        let _ = self.command_tx.send(ChatCommand::Hide);
    }

    /// Add a message to the chat window
    pub fn add_message(&self, msg: ChatMessage) {
        let _ = self.command_tx.send(ChatCommand::AddMessage(msg));
    }

    /// Check for outgoing messages from the user
    pub fn poll_outgoing(&self) -> Option<ChatMessage> {
        if let Ok(rx) = self.message_rx.lock() {
            rx.try_recv().ok()
        } else {
            None
        }
    }

    /// Close the chat window
    #[allow(dead_code)]
    pub fn close(&self) {
        let _ = self.command_tx.send(ChatCommand::Close);
    }
}

#[cfg(windows)]
fn run_chat_window(command_rx: Receiver<ChatCommand>, _message_tx: Sender<ChatMessage>) {
    info!("Starting chat window thread");

    // For now, we'll use a simple message box approach
    // A full implementation would create a proper window with a text input

    // Process commands
    loop {
        match command_rx.recv() {
            Ok(ChatCommand::Show) => {
                info!("Chat window: Show requested");
                // Show a simple notification that chat is available
            }
            Ok(ChatCommand::Hide) => {
                info!("Chat window: Hide requested");
            }
            Ok(ChatCommand::AddMessage(msg)) => {
                info!("Chat message received: {} - {}", msg.sender, msg.content);

                // Show the message to the user via a message box (simple implementation)
                let title = format!("Message from {}", msg.sender);
                let content = msg.content.clone();

                // Spawn a thread to show the message box (non-blocking)
                thread::spawn(move || {
                    show_message_box_internal(&title, &content);
                });
            }
            Ok(ChatCommand::Close) => {
                info!("Chat window: Close requested");
                break;
            }
            Err(_) => {
                // Channel closed
                break;
            }
        }
    }
}

#[cfg(windows)]
fn show_message_box_internal(title: &str, message: &str) {
    use std::ffi::OsStr;
    use std::os::windows::ffi::OsStrExt;

    let title_wide: Vec<u16> = OsStr::new(title)
        .encode_wide()
        .chain(std::iter::once(0))
        .collect();
    let message_wide: Vec<u16> = OsStr::new(message)
        .encode_wide()
        .chain(std::iter::once(0))
        .collect();

    unsafe {
        MessageBoxW(
            None,
            PCWSTR(message_wide.as_ptr()),
            PCWSTR(title_wide.as_ptr()),
            MB_OK | MB_ICONINFORMATION | MB_TOPMOST | MB_SETFOREGROUND,
        );
    }
}

#[cfg(not(windows))]
fn run_chat_window(_command_rx: Receiver<ChatCommand>, _message_tx: Sender<ChatMessage>) {
    // No-op on non-Windows
}
