# Copyright (c) 2025 CoReason, Inc.
#
# This software is proprietary and dual-licensed.
# Licensed under the Prosperity Public License 3.0 (the "License").
# A copy of the license is available at https://prosperitylicense.com/versions/3.0.0
# For details, see the LICENSE file.
# Commercial use beyond a 30-day trial requires a separate license.
#
# Source Code: https://github.com/CoReason-AI/coreason_navigator

from typing import List, Literal, Optional, Union

from pydantic import BaseModel, Field


class ElementBoundingBox(BaseModel):
    """
    Represents a bounding box for an interactive element on the screen.

    Attributes:
        element_id: Unique identifier for the element (e.g., backend Node ID).
        x: X coordinate of the top-left corner.
        y: Y coordinate of the top-left corner.
        width: Width of the element.
        height: Height of the element.
        tag_name: HTML tag name (e.g., 'button', 'input').
        text: Visible text or label of the element.
        attributes: Key attributes (e.g., role, type).
    """

    element_id: str = Field(..., description="Unique identifier for the element (e.g., backend Node ID)")
    x: float = Field(..., description="X coordinate of the top-left corner")
    y: float = Field(..., description="Y coordinate of the top-left corner")
    width: float = Field(..., description="Width of the element")
    height: float = Field(..., description="Height of the element")
    tag_name: str = Field(default="", description="HTML tag name (e.g., 'button', 'input')")
    text: str = Field(default="", description="Visible text or label of the element")
    attributes: dict[str, str] = Field(default_factory=dict, description="Key attributes (e.g., role, type)")


class BrowserState(BaseModel):
    """
    Represents the current snapshot state of the browser.

    Attributes:
        url: Current page URL.
        title: Current page title.
        screenshot_base64: Base64 encoded original screenshot.
        som_screenshot_base64: Screenshot with Set-of-Marks (bounding boxes + IDs) overlaid.
        interactive_elements: List of interactive elements detected on the page.
    """

    url: str = Field(..., description="Current page URL")
    title: str = Field(..., description="Current page title")
    screenshot_base64: str = Field(..., description="Base64 encoded original screenshot")
    som_screenshot_base64: Optional[str] = Field(
        default=None, description="Screenshot with Set-of-Marks (bounding boxes + IDs) overlaid."
    )
    interactive_elements: List[ElementBoundingBox] = Field(
        default_factory=list, description="List of interactive elements detected on the page"
    )


# Action definitions
class Action(BaseModel):
    """Base class for all browser actions."""

    action_type: str


class ClickAction(Action):
    """
    Action to click on an element.

    Attributes:
        action_type: Always "click".
        target_id: The ID of the element to click.
        x: The x coordinate to click.
        y: The y coordinate to click.
    """

    action_type: Literal["click"] = "click"
    target_id: Optional[str] = None
    x: Optional[float] = None
    y: Optional[float] = None


class TypeAction(Action):
    """
    Action to type text.

    Attributes:
        action_type: Always "type".
        text: The text to type.
        press_enter: Whether to press enter after typing.
    """

    action_type: Literal["type"] = "type"
    text: str
    press_enter: bool = True


class ScrollAction(Action):
    """
    Action to scroll the page.

    Attributes:
        action_type: Always "scroll".
        direction: Direction to scroll ("up", "down", "left", "right").
        amount: Amount of pixels to scroll.
    """

    action_type: Literal["scroll"] = "scroll"
    direction: Literal["up", "down", "left", "right"] = "down"
    amount: int


class GotoAction(Action):
    """
    Action to navigate to a URL.

    Attributes:
        action_type: Always "goto".
        url: The URL to navigate to.
    """

    action_type: Literal["goto"] = "goto"
    url: str


class WaitAction(Action):
    """
    Action to wait for a certain state.

    Attributes:
        action_type: Always "wait".
        state: The load state to wait for ("load", "domcontentloaded", "networkidle").
    """

    action_type: Literal["wait"] = "wait"
    state: Literal["load", "domcontentloaded", "networkidle"] = "networkidle"


class ScreenshotAction(Action):
    """
    Action to take a screenshot.

    Attributes:
        action_type: Always "screenshot".
    """

    action_type: Literal["screenshot"] = "screenshot"


BrowserAction = Union[ClickAction, TypeAction, ScrollAction, GotoAction, WaitAction, ScreenshotAction]
