use crate::{
    config::Config,
    core::{handle, timer::Timer, tray::Tray},
    log_err, logging,
    process::AsyncHandler,
    state::proxy::ProxyRequestCache,
    utils::{logging::Type, window_manager::WindowManager},
};

use crate::logging_error;

use anyhow::{Context, Result};
use delay_timer::prelude::TaskBuilder;
use std::sync::atomic::{AtomicBool, Ordering};
use tauri::{Listener, Manager};

const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task";

// 添加退出轻量模式的锁，防止并发调用
static EXITING_LIGHTWEIGHT: AtomicBool = AtomicBool::new(false);

static IS_IN_LIGHTWEIGHT: AtomicBool = AtomicBool::new(false);

fn inner_set_lightweight_mode(value: bool) -> bool {
    if value {
        logging!(info, Type::Lightweight, true, "轻量模式已开启");
    } else {
        logging!(info, Type::Lightweight, true, "轻量模式已关闭");
    }
    IS_IN_LIGHTWEIGHT.store(value, Ordering::SeqCst);
    value
}

fn inner_get_lightweight_mode() -> bool {
    IS_IN_LIGHTWEIGHT.load(Ordering::SeqCst) || !WindowManager::is_main_window_exists()
}

pub async fn run_once_auto_lightweight() {
    let verge_config = Config::verge().await;
    let enable_auto = verge_config
        .data_mut()
        .enable_auto_light_weight_mode
        .unwrap_or(false);
    let is_silent_start = verge_config
        .latest_ref()
        .enable_silent_start
        .unwrap_or(false);

    if !(enable_auto && is_silent_start) {
        logging!(
            info,
            Type::Lightweight,
            true,
            "不满足静默启动且自动进入轻量模式的条件，跳过自动进入轻量模式"
        );
        return;
    }

    logging!(
        info,
        Type::Lightweight,
        true,
        "在静默启动的情况下，创建窗口再添加自动进入轻量模式窗口监听器"
    );

    enable_auto_light_weight_mode().await;

    if let Err(e) = Tray::global().update_part().await {
        log::warn!("Failed to update tray: {e}");
    }
}

pub async fn auto_lightweight_mode_init() -> Result<()> {
    let is_silent_start =
        { Config::verge().await.latest_ref().enable_silent_start }.unwrap_or(false);
    let enable_auto = {
        Config::verge()
            .await
            .latest_ref()
            .enable_auto_light_weight_mode
    }
    .unwrap_or(false);

    if enable_auto && !is_silent_start {
        logging!(
            info,
            Type::Lightweight,
            true,
            "非静默启动直接挂载自动进入轻量模式监听器！"
        );
        set_lightweight_mode(true).await;
        enable_auto_light_weight_mode().await;
    }

    Ok(())
}

// 检查是否处于轻量模式
pub fn is_in_lightweight_mode() -> bool {
    IS_IN_LIGHTWEIGHT.load(Ordering::SeqCst)
}

// 设置轻量模式状态
pub async fn set_lightweight_mode(value: bool) {
    if inner_get_lightweight_mode() != value {
        inner_set_lightweight_mode(value);
        // 只有在状态可用时才触发托盘更新
        if let Err(e) = Tray::global().update_part().await {
            log::warn!("Failed to update tray: {e}");
        }
    }
}

pub async fn enable_auto_light_weight_mode() {
    if let Err(e) = Timer::global().init().await {
        logging!(error, Type::Lightweight, "Failed to initialize timer: {e}");
        return;
    }
    logging!(info, Type::Lightweight, true, "开启自动轻量模式");
    setup_window_close_listener();
    setup_webview_focus_listener();
}

pub fn disable_auto_light_weight_mode() {
    logging!(info, Type::Lightweight, true, "关闭自动轻量模式");
    let _ = cancel_light_weight_timer();
    cancel_window_close_listener();
}

pub async fn entry_lightweight_mode() {
    use crate::utils::window_manager::WindowManager;

    let result = WindowManager::hide_main_window();
    logging!(
        info,
        Type::Lightweight,
        true,
        "轻量模式隐藏窗口结果: {:?}",
        result
    );

    if let Some(window) = handle::Handle::global().get_window() {
        if let Some(webview) = window.get_webview_window("main") {
            let _ = webview.destroy();
        }
        #[cfg(target_os = "macos")]
        handle::Handle::global().set_activation_policy_accessory();
    }
    set_lightweight_mode(true).await;
    let _ = cancel_light_weight_timer();
    ProxyRequestCache::global().clean_default_keys();

    // 更新托盘显示
    logging_error!(Type::Lightweight, true, Tray::global().update_part().await);
}

// 添加从轻量模式恢复的函数
pub async fn exit_lightweight_mode() {
    // 使用原子操作检查是否已经在退出过程中，防止并发调用
    if EXITING_LIGHTWEIGHT
        .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
        .is_err()
    {
        logging!(
            info,
            Type::Lightweight,
            true,
            "轻量模式退出操作已在进行中，跳过重复调用"
        );
        return;
    }

    // 使用defer确保无论如何都会重置标志
    let _guard = scopeguard::guard((), |_| {
        EXITING_LIGHTWEIGHT.store(false, Ordering::SeqCst);
    });

    // 确保当前确实处于轻量模式才执行退出操作
    if !is_in_lightweight_mode() {
        logging!(info, Type::Lightweight, true, "当前不在轻量模式，无需退出");
        return;
    }

    set_lightweight_mode(false).await;

    // macOS激活策略
    #[cfg(target_os = "macos")]
    handle::Handle::global().set_activation_policy_regular();

    // 重置UI就绪状态
    crate::utils::resolve::ui::reset_ui_ready();

    // 更新托盘显示
    let _tray = crate::core::tray::Tray::global();
}

#[cfg(target_os = "macos")]
pub async fn add_light_weight_timer() {
    logging_error!(Type::Lightweight, setup_light_weight_timer().await);
}

fn setup_window_close_listener() -> u32 {
    if let Some(window) = handle::Handle::global().get_window() {
        let handler = window.listen("tauri://close-requested", move |_event| {
            std::mem::drop(AsyncHandler::spawn(|| async {
                if let Err(e) = setup_light_weight_timer().await {
                    log::warn!("Failed to setup light weight timer: {e}");
                }
            }));
            logging!(
                info,
                Type::Lightweight,
                true,
                "监听到关闭请求，开始轻量模式计时"
            );
        });
        return handler;
    }
    0
}

fn setup_webview_focus_listener() -> u32 {
    if let Some(window) = handle::Handle::global().get_window() {
        let handler = window.listen("tauri://focus", move |_event| {
            log_err!(cancel_light_weight_timer());
            logging!(
                info,
                Type::Lightweight,
                "监听到窗口获得焦点，取消轻量模式计时"
            );
        });
        return handler;
    }
    0
}

fn cancel_window_close_listener() {
    if let Some(window) = handle::Handle::global().get_window() {
        window.unlisten(setup_window_close_listener());
        logging!(info, Type::Lightweight, true, "取消了窗口关闭监听");
    }
}

async fn setup_light_weight_timer() -> Result<()> {
    Timer::global().init().await?;
    let once_by_minutes = Config::verge()
        .await
        .latest_ref()
        .auto_light_weight_minutes
        .unwrap_or(10);

    // 获取task_id
    let task_id = {
        Timer::global()
            .timer_count
            .fetch_add(1, std::sync::atomic::Ordering::Relaxed)
    };

    // 创建任务
    let task = TaskBuilder::default()
        .set_task_id(task_id)
        .set_maximum_parallel_runnable_num(1)
        .set_frequency_once_by_minutes(once_by_minutes)
        .spawn_async_routine(move || async move {
            logging!(info, Type::Timer, true, "计时器到期，开始进入轻量模式");
            entry_lightweight_mode().await;
        })
        .context("failed to create timer task")?;

    // 添加任务到定时器
    {
        let delay_timer = Timer::global().delay_timer.write();
        delay_timer
            .add_task(task)
            .context("failed to add timer task")?;
    }

    // 更新任务映射
    {
        let mut timer_map = Timer::global().timer_map.write();
        let timer_task = crate::core::timer::TimerTask {
            task_id,
            interval_minutes: once_by_minutes,
            last_run: chrono::Local::now().timestamp(),
        };
        timer_map.insert(LIGHT_WEIGHT_TASK_UID.to_string(), timer_task);
    }

    logging!(
        info,
        Type::Timer,
        true,
        "计时器已设置，{} 分钟后将自动进入轻量模式",
        once_by_minutes
    );

    Ok(())
}

fn cancel_light_weight_timer() -> Result<()> {
    let mut timer_map = Timer::global().timer_map.write();
    let delay_timer = Timer::global().delay_timer.write();

    if let Some(task) = timer_map.remove(LIGHT_WEIGHT_TASK_UID) {
        delay_timer
            .remove_task(task.task_id)
            .context("failed to remove timer task")?;
        logging!(info, Type::Timer, true, "计时器已取消");
    }

    Ok(())
}
