use crate::{
    conf::{self, ChatConfJson},
    utils,
};
use tauri::{
    AboutMetadata, AppHandle, CustomMenuItem, Manager, Menu, MenuItem, Submenu, SystemTray,
    SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, WindowMenuEvent,
};
use tauri_plugin_positioner::{on_tray_event, Position, WindowExt};

// --- Menu
pub fn init() -> Menu {
    let chat_conf = ChatConfJson::get_chat_conf();
    let name = "ChatGPT";
    let app_menu = Submenu::new(
        name,
        Menu::new()
            .add_native_item(MenuItem::About(name.into(), AboutMetadata::default()))
            .add_native_item(MenuItem::Services)
            .add_native_item(MenuItem::Separator)
            .add_native_item(MenuItem::Hide)
            .add_native_item(MenuItem::HideOthers)
            .add_native_item(MenuItem::ShowAll)
            .add_native_item(MenuItem::Separator)
            .add_native_item(MenuItem::Quit),
    );

    let stay_on_top =
        CustomMenuItem::new("stay_on_top".to_string(), "Stay On Top").accelerator("CmdOrCtrl+T");
    let titlebar =
        CustomMenuItem::new("titlebar".to_string(), "Titlebar").accelerator("CmdOrCtrl+B");
    let theme_light = CustomMenuItem::new("theme_light".to_string(), "Light");
    let theme_dark = CustomMenuItem::new("theme_dark".to_string(), "Dark");
    let is_dark = chat_conf.theme == "Dark";

    let stay_on_top_menu = if chat_conf.stay_on_top {
        stay_on_top.selected()
    } else {
        stay_on_top
    };
    let titlebar_menu = if chat_conf.titlebar {
        titlebar.selected()
    } else {
        titlebar
    };

    let preferences_menu = Submenu::new(
        "Preferences",
        Menu::with_items([
            CustomMenuItem::new("control_center".to_string(), "Control Center")
                .accelerator("CmdOrCtrl+Shift+P")
                .into(),
            MenuItem::Separator.into(),
            Submenu::new(
                "Theme",
                Menu::new()
                    .add_item(if is_dark {
                        theme_light
                    } else {
                        theme_light.selected()
                    })
                    .add_item(if is_dark {
                        theme_dark.selected()
                    } else {
                        theme_dark
                    }),
            )
            .into(),
            stay_on_top_menu.into(),
            #[cfg(target_os = "macos")]
            titlebar_menu.into(),
            #[cfg(target_os = "macos")]
            CustomMenuItem::new("hide_dock_icon".to_string(), "Hide Dock Icon").into(),
            CustomMenuItem::new("inject_script".to_string(), "Inject Script")
                .accelerator("CmdOrCtrl+J")
                .into(),
            MenuItem::Separator.into(),
            CustomMenuItem::new("sync_prompts".to_string(), "Sync Prompts").into(),
            MenuItem::Separator.into(),
            CustomMenuItem::new("go_conf".to_string(), "Go to Config")
                .accelerator("CmdOrCtrl+Shift+G")
                .into(),
            CustomMenuItem::new("clear_conf".to_string(), "Clear Config")
                .accelerator("CmdOrCtrl+Shift+D")
                .into(),
            CustomMenuItem::new("restart".to_string(), "Restart ChatGPT")
                .accelerator("CmdOrCtrl+Shift+R")
                .into(),
            MenuItem::Separator.into(),
            CustomMenuItem::new("awesome".to_string(), "Awesome ChatGPT")
                .accelerator("CmdOrCtrl+Shift+A")
                .into(),
        ]),
    );

    let edit_menu = Submenu::new(
        "Edit",
        Menu::new()
            .add_native_item(MenuItem::Undo)
            .add_native_item(MenuItem::Redo)
            .add_native_item(MenuItem::Separator)
            .add_native_item(MenuItem::Cut)
            .add_native_item(MenuItem::Copy)
            .add_native_item(MenuItem::Paste)
            .add_native_item(MenuItem::SelectAll),
    );

    let view_menu = Submenu::new(
        "View",
        Menu::new()
            .add_item(
                CustomMenuItem::new("go_back".to_string(), "Go Back").accelerator("CmdOrCtrl+Left"),
            )
            .add_item(
                CustomMenuItem::new("go_forward".to_string(), "Go Forward")
                    .accelerator("CmdOrCtrl+Right"),
            )
            .add_item(
                CustomMenuItem::new("scroll_top".to_string(), "Scroll to Top of Screen")
                    .accelerator("CmdOrCtrl+Up"),
            )
            .add_item(
                CustomMenuItem::new("scroll_bottom".to_string(), "Scroll to Bottom of Screen")
                    .accelerator("CmdOrCtrl+Down"),
            )
            .add_native_item(MenuItem::Separator)
            .add_item(
                CustomMenuItem::new("reload".to_string(), "Refresh the Screen")
                    .accelerator("CmdOrCtrl+R"),
            ),
    );

    let window_menu = Submenu::new(
        "Window",
        Menu::new()
            .add_native_item(MenuItem::Minimize)
            .add_native_item(MenuItem::Zoom),
    );

    let help_menu = Submenu::new(
        "Help",
        Menu::new()
            .add_item(CustomMenuItem::new(
                "chatgpt_log".to_string(),
                "ChatGPT Log",
            ))
            .add_item(CustomMenuItem::new("update_log".to_string(), "Update Log"))
            .add_item(CustomMenuItem::new("report_bug".to_string(), "Report Bug"))
            .add_item(
                CustomMenuItem::new("dev_tools".to_string(), "Toggle Developer Tools")
                    .accelerator("CmdOrCtrl+Shift+I"),
            ),
    );

    Menu::new()
        .add_submenu(app_menu)
        .add_submenu(preferences_menu)
        .add_submenu(edit_menu)
        .add_submenu(view_menu)
        .add_submenu(window_menu)
        .add_submenu(help_menu)
}

// --- Menu Event
pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
    let win = Some(event.window()).unwrap();
    let app = win.app_handle();
    let state: tauri::State<conf::ChatState> = app.state();
    let script_path = utils::script_path().to_string_lossy().to_string();
    let menu_id = event.menu_item_id();

    let core_window = app.get_window("core").unwrap();
    let menu_handle = core_window.menu_handle();

    match menu_id {
        // Preferences
        "control_center" => app.get_window("main").unwrap().show().unwrap(),
        "restart" => tauri::api::process::restart(&app.env()),
        "inject_script" => open(&app, script_path),
        "go_conf" => utils::open_file(utils::chat_root()),
        "clear_conf" => utils::clear_conf(&app),
        "awesome" => open(&app, conf::AWESOME_URL.to_string()),
        "sync_prompts" => {
            tauri::api::dialog::ask(
                app.get_window("main").as_ref(),
                "Sync Prompts",
                "Data sync will enable all prompts, are you sure you want to sync?",
                move |is_restart| {
                    if is_restart {
                        app.get_window("main")
                            .unwrap()
                            .eval("window.__sync_prompts && window.__sync_prompts()")
                            .unwrap()
                    }
                },
            );
        }
        "hide_dock_icon" => {
            ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app)).unwrap()
        }
        "titlebar" => {
            let chat_conf = conf::ChatConfJson::get_chat_conf();
            ChatConfJson::amend(
                &serde_json::json!({ "titlebar": !chat_conf.titlebar }),
                None,
            )
            .unwrap();
            tauri::api::process::restart(&app.env());
        }
        "theme_light" | "theme_dark" => {
            let theme = if menu_id == "theme_dark" {
                "Dark"
            } else {
                "Light"
            };
            ChatConfJson::amend(&serde_json::json!({ "theme": theme }), Some(app)).unwrap();
        }
        "stay_on_top" => {
            let mut stay_on_top = state.stay_on_top.lock().unwrap();
            *stay_on_top = !*stay_on_top;
            menu_handle
                .get_item(menu_id)
                .set_selected(*stay_on_top)
                .unwrap();
            win.set_always_on_top(*stay_on_top).unwrap();
            ChatConfJson::amend(&serde_json::json!({ "stay_on_top": *stay_on_top }), None).unwrap();
        }
        // View
        "reload" => win.eval("window.location.reload()").unwrap(),
        "go_back" => win.eval("window.history.go(-1)").unwrap(),
        "go_forward" => win.eval("window.history.go(1)").unwrap(),
        "scroll_top" => win
            .eval(
                r#"window.scroll({
                top: 0,
                left: 0,
                behavior: "smooth"
                })"#,
            )
            .unwrap(),
        "scroll_bottom" => win
            .eval(
                r#"window.scroll({
                top: document.body.scrollHeight,
                left: 0,
                behavior: "smooth"})"#,
            )
            .unwrap(),
        // Help
        "chatgpt_log" => utils::open_file(utils::chat_root().join("chatgpt.log")),
        "update_log" => open(&app, conf::UPDATE_LOG_URL.to_string()),
        "report_bug" => open(&app, conf::ISSUES_URL.to_string()),
        "dev_tools" => {
            win.open_devtools();
            win.close_devtools();
        }
        _ => (),
    }
}

// --- SystemTray Menu
pub fn tray_menu() -> SystemTray {
    SystemTray::new().with_menu(
        SystemTrayMenu::new()
            .add_item(CustomMenuItem::new(
                "control_center".to_string(),
                "Control Center",
            ))
            .add_item(CustomMenuItem::new(
                "show_dock_icon".to_string(),
                "Show Dock Icon",
            ))
            .add_item(CustomMenuItem::new(
                "hide_dock_icon".to_string(),
                "Hide Dock Icon",
            ))
            .add_native_item(SystemTrayMenuItem::Separator)
            .add_item(CustomMenuItem::new("quit".to_string(), "Quit ChatGPT")),
    )
}

// --- SystemTray Event
pub fn tray_handler(handle: &AppHandle, event: SystemTrayEvent) {
    on_tray_event(handle, &event);

    let app = handle.clone();

    match event {
        SystemTrayEvent::LeftClick { .. } => {
            let chat_conf = conf::ChatConfJson::get_chat_conf();

            if !chat_conf.hide_dock_icon {
                let core_win = handle.get_window("core").unwrap();
                core_win.minimize().unwrap();
            }

            let tray_win = handle.get_window("tray").unwrap();
            tray_win.move_window(Position::TrayCenter).unwrap();

            if tray_win.is_visible().unwrap() {
                tray_win.hide().unwrap();
            } else {
                tray_win.show().unwrap();
            }
        }
        SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
            "control_center" => app.get_window("main").unwrap().show().unwrap(),
            "restart" => tauri::api::process::restart(&handle.env()),
            "show_dock_icon" => {
                ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": false }), Some(app))
                    .unwrap();
            }
            "hide_dock_icon" => {
                let chat_conf = conf::ChatConfJson::get_chat_conf();
                if !chat_conf.hide_dock_icon {
                    ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app))
                        .unwrap();
                }
            }
            "quit" => std::process::exit(0),
            _ => (),
        },
        _ => (),
    }
}

pub fn open(app: &AppHandle, path: String) {
    tauri::api::shell::open(&app.shell_scope(), path, None).unwrap();
}
