use ksni::menu::StandardItem;
use ksni::{Category, ToolTip, Tray, TrayMethods};
use std::path::PathBuf;
use std::sync::mpsc;

pub enum TrayCommand {
    Show,
    QuickAdd,
    LogExpense,
    LogIncome,
    Quit,
}

struct OutlayTray {
    sender: mpsc::Sender<TrayCommand>,
    icon_theme_path: String,
}

impl Tray for OutlayTray {
    fn id(&self) -> String {
        "outlay".into()
    }

    fn title(&self) -> String {
        "Outlay".into()
    }

    fn icon_name(&self) -> String {
        "io.github.outlay".into()
    }

    fn icon_theme_path(&self) -> String {
        self.icon_theme_path.clone()
    }

    fn category(&self) -> Category {
        Category::ApplicationStatus
    }

    fn tool_tip(&self) -> ToolTip {
        ToolTip {
            title: "Outlay - Personal Finance".into(),
            description: String::new(),
            icon_name: String::new(),
            icon_pixmap: Vec::new(),
        }
    }

    fn activate(&mut self, _x: i32, _y: i32) {
        self.sender.send(TrayCommand::Show).ok();
    }

    fn menu(&self) -> Vec<ksni::MenuItem<Self>> {
        vec![
            StandardItem {
                label: "Show Outlay".into(),
                activate: Box::new(|tray: &mut Self| {
                    tray.sender.send(TrayCommand::Show).ok();
                }),
                ..Default::default()
            }
            .into(),
            ksni::MenuItem::Separator,
            StandardItem {
                label: "Quick Add".into(),
                activate: Box::new(|tray: &mut Self| {
                    tray.sender.send(TrayCommand::QuickAdd).ok();
                }),
                ..Default::default()
            }
            .into(),
            StandardItem {
                label: "Log Expense".into(),
                activate: Box::new(|tray: &mut Self| {
                    tray.sender.send(TrayCommand::LogExpense).ok();
                }),
                ..Default::default()
            }
            .into(),
            StandardItem {
                label: "Log Income".into(),
                activate: Box::new(|tray: &mut Self| {
                    tray.sender.send(TrayCommand::LogIncome).ok();
                }),
                ..Default::default()
            }
            .into(),
            ksni::MenuItem::Separator,
            StandardItem {
                label: "Quit".into(),
                activate: Box::new(|tray: &mut Self| {
                    tray.sender.send(TrayCommand::Quit).ok();
                }),
                ..Default::default()
            }
            .into(),
        ]
    }
}

fn find_icon_theme_path() -> String {
    let exe_path = std::env::current_exe().unwrap_or_default();
    let exe_dir = exe_path.parent().unwrap_or(std::path::Path::new("."));

    let candidates = [
        exe_dir.join("../../outlay-gtk/data/icons"),
        exe_dir.join("../share/icons"),
        PathBuf::from("/usr/share/icons"),
    ];

    for candidate in &candidates {
        if candidate.exists() {
            if let Ok(resolved) = candidate.canonicalize() {
                return resolved.to_string_lossy().into_owned();
            }
        }
    }

    String::new()
}

pub fn spawn_tray(sender: mpsc::Sender<TrayCommand>) {
    let icon_theme_path = find_icon_theme_path();

    let tray = OutlayTray {
        sender,
        icon_theme_path,
    };

    std::thread::spawn(move || {
        let rt = tokio::runtime::Builder::new_current_thread()
            .enable_all()
            .build()
            .expect("Failed to create tokio runtime for tray");

        rt.block_on(async {
            match tray.spawn().await {
                Ok(_handle) => {
                    std::future::pending::<()>().await;
                }
                Err(e) => {
                    eprintln!("[tray] Failed to register: {:?}", e);
                }
            }
        });
    });
}
