use crate::constants::window::*;
use crate::window::{
    WindowLabel,
    derive::{PopupLocation, PopupSize, TargetLocation},
    util::get_monitor_for_window,
};
use tauri::{AppHandle, Manager, Runtime, WebviewUrl, WebviewWindowBuilder};

/// 创建弹出框窗口（内部实现）
pub async fn create_popup_window_impl<R: Runtime>(app: &AppHandle<R>, target: &TargetLocation, placement: &str) -> Result<(), String> {
    // 获取屏幕尺寸，优先为main窗口所在屏幕，主窗口没有打开时，才找主屏幕
    let monitor: tauri::Monitor = get_monitor_for_window(app)?;

    // 使用动态计算的弹出窗口尺寸
    let popup_size = calculate_popup_size_sync();
    let page_size = monitor.size().to_logical(monitor.scale_factor());
    // 计算弹出框位置和大小
    let popup_location = calculate_placement(target, &popup_size, placement, &page_size).await?;

    let label = WindowLabel::POPUP.as_ref();
    // 检查是否已经存在名为"popup"的窗口
    if let Some(popup_window) = app.get_webview_window(label) {
        // 如果窗口已存在，直接关闭它
        let _ = popup_window.close();
    }
    log::info!("创建弹出框窗口: {:?}", popup_location);

    let url = format!("popup-window.html?placement={}", popup_location.placement); // 创建弹出框窗口
    WebviewWindowBuilder::new(app, label, WebviewUrl::App(url.into()))
        .title("弹出框")
        .inner_size(popup_location.width as f64, popup_location.height as f64)
        .position(popup_location.x as f64, popup_location.y as f64)
        .resizable(false)
        .transparent(true)
        .decorations(false)
        .shadow(false)
        .focusable(true)
        .focused(true)
        .accept_first_mouse(true)
        .skip_taskbar(true)
        .always_on_top(true)
        .visible(true)
        .build()
        .map_err(|e| format!("创建弹出框窗口失败: {}", e))?;

    Ok(())
}

/// 根据用户登录状态和课程选择情况动态计算弹出窗口高度
pub fn calculate_popup_size_sync() -> PopupSize {
    // 默认基础项目数
    let item_num = 3;
    // 根据项目数计算高度，每个项目40像素，加上边距2像素
    let popup_height = 40 * item_num + 2;
    let popup_width = 180;

    // 返回计算得到的弹出窗口尺寸
    PopupSize {
        width: popup_width,
        height: popup_height,
    }
}

/// 计算弹出框位置
pub async fn calculate_placement(target: &TargetLocation, popup_size: &PopupSize, placement: &str, page_size: &tauri::LogicalSize<i32>) -> Result<PopupLocation, String> {
    let margin = 12; // 箭头距离触发元素的距离
    let mar = 12; // 距离屏幕边缘的最小距离

    let page_width = page_size.width;
    let page_height = page_size.height;

    // 点击dom宽高
    let target_width = target.width;
    let target_height = target.height;
    // 点击dom右上角的坐标
    let target_x = target.x;
    let target_y = target.y;
    // 点击dom中心点坐标
    let center_x = target_x + (target_width / 2) as i32;
    let center_y = target_y + (target_height / 2) as i32;
    // 弹出框的宽高
    let bubble_width = popup_size.width;
    let bubble_height = popup_size.height;

    // 如果placement为"center"，则直接返回屏幕中央位置
    if placement == PLACEMENT_CENTER {
        return Ok(calculate_center_position(popup_size, page_size));
    }

    // 上面足够
    let top_enough = bubble_height as i32 + margin + mar < target_y;
    // 下面足够
    let bottom_enough = (target_y + target_height as i32 + bubble_height as i32 + margin + mar) < page_height;
    // 左面足够
    let left_enough = target_x - bubble_width as i32 - margin - mar >= 0;
    // 右面足够
    let right_enough = target_x + target_width as i32 + bubble_width as i32 + margin + mar < page_width;
    // 屏幕宽度足够
    let width_enough = page_width > bubble_width as i32 + mar * 2;
    // 屏幕高度足够
    let height_enough = page_height > bubble_height as i32 + mar * 2;

    if (placement == PLACEMENT_AUTO || placement == PLACEMENT_TOP) && top_enough && width_enough {
        get_top_bottom_placement(PLACEMENT_TOP, target, popup_size, margin, mar, center_x, page_width)
    } else if (placement == PLACEMENT_AUTO || placement == PLACEMENT_BOTTOM) && bottom_enough && width_enough {
        get_top_bottom_placement(PLACEMENT_BOTTOM, target, popup_size, margin, mar, center_x, page_width)
    } else if (placement == PLACEMENT_AUTO || placement == PLACEMENT_LEFT) && left_enough && height_enough {
        get_left_right_placement(PLACEMENT_LEFT, target, popup_size, margin, mar, center_y, page_height)
    } else if (placement == PLACEMENT_AUTO || placement == PLACEMENT_RIGHT) && right_enough && height_enough {
        get_left_right_placement(PLACEMENT_RIGHT, target, popup_size, margin, mar, center_y, page_height)
    } else {
        let popup_y = center_y + (target_height as i32) / 2 + margin;
        Ok(PopupLocation {
            enough_show: false,
            placement: PLACEMENT_CENTER.to_string(),
            x: 0,
            y: popup_y,
            width: popup_size.width,
            height: popup_size.height,
        })
    }
}

/// 计算屏幕中央位置
pub fn calculate_center_position(popup_size: &PopupSize, page_size: &tauri::LogicalSize<i32>) -> PopupLocation {
    let page_width = page_size.width;
    let page_height = page_size.height;

    let popup_x = (page_width - popup_size.width as i32) / 2;
    let popup_y = (page_height - popup_size.height as i32) / 2;

    PopupLocation {
        enough_show: true,
        placement: PLACEMENT_CENTER.to_string(),
        x: popup_x,
        y: popup_y,
        width: popup_size.width,
        height: popup_size.height,
    }
}

/// 上或者下足够并且宽度也足够时的位置计算
fn get_top_bottom_placement(
    placement: &str,
    target: &TargetLocation,
    popup_size: &PopupSize,
    margin: i32,
    mar: i32,
    center_x: i32,
    page_width: i32,
) -> Result<PopupLocation, String> {
    let popup_y = if placement == "bottom" {
        target.y + target.height as i32 + margin
    } else {
        target.y - popup_size.height as i32 - margin
    };

    let right_x = center_x - (popup_size.width as i32) / 2;
    let left_x = center_x + (popup_size.width as i32) / 2;
    let mut popup_x = mar;

    if right_x >= mar && page_width - left_x >= mar {
        popup_x = right_x;
    } else if page_width - left_x >= mar {
        popup_x = mar;
    } else if right_x >= mar {
        popup_x = page_width - popup_size.width as i32 - mar;
    }

    Ok(PopupLocation {
        enough_show: true,
        placement: placement.to_string(),
        y: popup_y,
        x: popup_x,
        width: popup_size.width,
        height: popup_size.height,
    })
}

/// 左或者右足够并且高度也足够时的位置计算
fn get_left_right_placement(
    placement: &str,
    target: &TargetLocation,
    popup_size: &PopupSize,
    margin: i32,
    mar: i32,
    center_y: i32,
    page_height: i32,
) -> Result<PopupLocation, String> {
    let popup_x = if placement == "left" {
        target.x - popup_size.width as i32 - margin
    } else {
        target.x + target.width as i32 + margin
    };

    let top_y = center_y - (popup_size.height as i32) / 2;
    let bottom_y = center_y + (popup_size.height as i32) / 2;
    let popup_y = if top_y >= mar && page_height - bottom_y >= mar {
        // 水平居中
        top_y
    } else if page_height - bottom_y >= mar {
        mar
    } else {
        page_height - popup_size.height as i32 - mar
    };

    Ok(PopupLocation {
        enough_show: true,
        placement: placement.to_string(),
        y: popup_y,
        x: popup_x,
        width: popup_size.width,
        height: popup_size.height,
    })
}
