"""Shared mutable runtime state for the TUI.

``AppState`` is the single source of truth used by render and handlers.
Most behavior in runtime modules mutates this dataclass in-place.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path

from .navigation import JumpHistory, JumpLocation
from ..tree_model import TreeEntry
from ..ui_theme import DEFAULT_THEME, UITheme


@dataclass
class AppState:
    """Mutable session state shared across input, navigation, and rendering.

    The runtime treats this as a central state bag: handlers mutate fields
    directly, and renderers read them to build each frame.
    """

    current_path: Path
    tree_root: Path
    expanded: set[Path]
    show_hidden: bool
    tree_entries: list[TreeEntry]
    selected_idx: int
    rendered: str
    lines: list[str]
    start: int
    tree_start: int
    text_x: int
    wrap_text: bool
    left_width: int
    right_width: int
    usable: int
    max_start: int
    last_right_width: int
    tree_roots: list[Path] = field(default_factory=list)
    workspace_expanded: list[set[Path]] = field(default_factory=list)
    theme_name: str = DEFAULT_THEME.name
    theme: UITheme = field(default_factory=lambda: DEFAULT_THEME)
    browser_visible: bool = True
    show_help: bool = False
    show_tree_sizes: bool = True
    dirty: bool = True
    status_message: str = ""
    status_message_until: float = 0.0
    skip_next_lf: bool = False
    count_buffer: str = ""
    last_click_idx: int = -1
    last_click_time: float = 0.0
    source_selection_anchor: tuple[int, int] | None = None
    source_selection_focus: tuple[int, int] | None = None
    tree_filter_active: bool = False
    tree_filter_editing: bool = False
    tree_filter_mode: str = "files"
    tree_filter_query: str = ""
    tree_filter_match_count: int = 0
    tree_filter_truncated: bool = False
    tree_filter_loading: bool = False
    tree_filter_prompt_row_visible: bool = True
    tree_filter_collapsed_dirs: set[Path] = field(default_factory=set)
    tree_filter_prev_browser_visible: bool | None = None
    tree_filter_origin: JumpLocation | None = None
    tree_render_expanded: set[Path] = field(default_factory=set)
    picker_active: bool = False
    picker_mode: str = "symbols"
    picker_focus: str = "query"
    picker_message: str = ""
    picker_query: str = ""
    picker_selected: int = 0
    picker_list_start: int = 0
    picker_matches: list[Path] = field(default_factory=list)
    picker_match_labels: list[str] = field(default_factory=list)
    picker_match_lines: list[int] = field(default_factory=list)
    picker_match_commands: list[str] = field(default_factory=list)
    picker_file_labels: list[str] = field(default_factory=list)
    picker_file_paths: list[Path] = field(default_factory=list)
    picker_file_workspace_sections: list[int] = field(default_factory=list)
    picker_file_labels_folded: list[str] = field(default_factory=list)
    picker_files_root: Path | None = None
    picker_files_roots_signature: tuple[str, ...] | None = None
    picker_files_show_hidden: bool | None = None
    picker_symbol_file: Path | None = None
    picker_symbol_labels: list[str] = field(default_factory=list)
    picker_symbol_lines: list[int] = field(default_factory=list)
    picker_command_ids: list[str] = field(default_factory=list)
    picker_command_labels: list[str] = field(default_factory=list)
    picker_prev_browser_visible: bool | None = None
    dir_preview_max_entries: int = 400
    dir_preview_truncated: bool = False
    dir_preview_path: Path | None = None
    preview_image_path: Path | None = None
    preview_image_format: str | None = None
    preview_is_git_diff: bool = False
    git_status_overlay: dict[Path, int] = field(default_factory=dict)
    git_status_last_refresh: float = 0.0
    jump_history: JumpHistory = field(default_factory=JumpHistory)
    named_marks: dict[str, JumpLocation] = field(default_factory=dict)
    pending_mark_set: bool = False
    pending_mark_jump: bool = False
    git_features_enabled: bool = True
