use nalgebra_glm::Vec4;
use serde::Serialize;
use winit::keyboard::KeyCode;

use nalgebra_glm::Vec2;

#[derive(Clone, Debug)]
pub(super) enum TestAction {
    MoveMouse(Vec2),
    MoveMouseToEntity(String),
    MousePress,
    MouseRelease,
    RightMousePress,
    RightMouseRelease,
    ClickAt(Vec2),
    ClickAtEntity(String),
    RightClickAt(Vec2),
    RightClickAtEntity(String),
    DragEntity(String, Vec2),
    SetSliderValue(String, f32),
    SelectDropdownOption(String, usize),
    SelectTab(String, usize),
    TypeChars(Vec<char>),
    PressAndReleaseKey(KeyCode),
    KeyDown(KeyCode),
    KeyUp(KeyCode),
    Scroll(Vec2),
    Screenshot(String),
    Assert(String, AssertKind),
    Log(String),
    Exit(bool),
}

#[derive(Clone, Debug)]
pub(super) enum AssertKind {
    Visible(String),
    NotVisible(String),
    Focused(String),
    NotFocused(String),
    Hovered(String),
    NotHovered(String),
    Disabled(String),
    NotDisabled(String),
    TextEquals(String, String),
    WidgetValueF32(String, f32, f32),
    WidgetValueBool(String, bool),
    WidgetValueUsize(String, usize),
    WidgetValueString(String, String),
    WidgetValueVec4(String, Vec4, f32),
    EventFired(EventMatch),
}

#[derive(Clone, Debug)]
pub(super) enum EventMatch {
    ButtonClicked,
    SliderChanged,
    ToggleChanged,
    TextInputSubmitted,
    TextInputChanged,
    CheckboxChanged,
    DropdownChanged,
    RadioChanged,
    TabChanged,
    DragValueChanged,
    MenuItemClicked,
    ColorPickerChanged,
    SelectableLabelClicked,
    ContextMenuItemClicked,
    TreeNodeSelected,
    TreeNodeToggled,
    ModalClosed,
    CommandPaletteExecuted,
    TileTabActivated,
    TileTabClosed,
    TileSplitterMoved,
    CanvasClicked,
    VirtualListItemClicked,
    TextAreaChanged,
    RichTextEditorChanged,
    DataGridFilterChanged,
    RangeSliderChanged,
    DataGridCellEdited,
    BreadcrumbClicked,
    SplitterChanged,
    MultiSelectChanged,
    DatePickerChanged,
    DragStarted,
    DragDropped,
    DragCancelled,
}

pub(super) struct ScheduledAction {
    pub frame: u64,
    pub action: TestAction,
}

#[derive(Clone, Debug, Serialize)]
pub struct UiTestResult {
    pub name: String,
    pub passed: bool,
    pub message: String,
}

#[derive(Clone, Debug, Serialize)]
pub(super) struct ResultRecord {
    pub name: String,
    pub passed: bool,
    pub message: String,
    pub frame: u64,
}

#[derive(Clone, Debug, Serialize)]
pub(super) struct ActionRecord {
    pub frame: u64,
    pub kind: String,
    pub target: Option<String>,
    pub position: Option<[f32; 2]>,
}

#[derive(Clone, Debug, Serialize)]
pub(super) struct ReportSummary {
    pub total: usize,
    pub passed: usize,
    pub failed: usize,
}

#[derive(Clone, Debug, Serialize)]
pub(super) struct TestReport {
    pub test_name: String,
    pub passed: bool,
    pub summary: ReportSummary,
    pub results: Vec<ResultRecord>,
    pub actions: Vec<ActionRecord>,
    pub screenshots: Vec<String>,
}
