"""Local file picker dialog for NiceGUI - from NiceGUI examples."""
import platform
import shutil
from pathlib import Path

from nicegui import events, ui


# -----------------------------------------------------------------------------
# Shared helpers (Windows drives toggle)
# -----------------------------------------------------------------------------

def _add_drives_toggle(dialog) -> None:
    """Add Windows drive selector; dialog must have .path and .update_grid()."""
    if platform.system() != "Windows":
        return
    try:
        import win32api
        drives = win32api.GetLogicalDriveStrings().split("\000")[:-1]
        dialog.drives_toggle = ui.toggle(
            drives, value=drives[0], on_change=lambda: _update_drive(dialog)
        )
    except ImportError:
        pass


def _update_drive(dialog) -> None:
    """Update dialog.path from drives_toggle and refresh grid."""
    if hasattr(dialog, "drives_toggle"):
        dialog.path = Path(dialog.drives_toggle.value).expanduser()
        dialog.update_grid()


# -----------------------------------------------------------------------------
# Public API
# -----------------------------------------------------------------------------

class LocalFilePicker(ui.dialog):
    """File picker that browses the local filesystem where NiceGUI runs."""

    def __init__(
        self,
        directory: str,
        *,
        upper_limit: str | None = ...,
        multiple: bool = False,
        show_hidden_files: bool = False,
    ) -> None:
        super().__init__()
        self.path = Path(directory).expanduser()
        if upper_limit is None:
            self.upper_limit = None
        else:
            self.upper_limit = Path(
                directory if upper_limit == ... else upper_limit
            ).expanduser()
        self.show_hidden_files = show_hidden_files

        with self, ui.card():
            self.add_drives_toggle()
            self.grid = ui.aggrid(
                {
                    "columnDefs": [{"field": "name", "headerName": "File"}],
                    "rowSelection": {
                        "mode": "multiRow" if multiple else "singleRow"
                    },
                },
                html_columns=[0],
            ).classes("w-96").on("cellDoubleClicked", self.handle_double_click)
            with ui.row().classes("w-full justify-end"):
                ui.button("Cancel", on_click=self.close).props("outline")
                ui.button("Ok", on_click=self._handle_ok)
            self.update_grid()

    def add_drives_toggle(self) -> None:
        _add_drives_toggle(self)

    def update_grid(self) -> None:
        paths = list(self.path.glob("*"))
        if not self.show_hidden_files:
            paths = [p for p in paths if not p.name.startswith(".")]
        paths.sort(key=lambda p: p.name.lower())
        paths.sort(key=lambda p: not p.is_dir())

        self.grid.options["rowData"] = [
            {
                "name": f"📁 {p.name} " if p.is_dir() else p.name,
                "path": str(p),
            }
            for p in paths
        ]
        if (self.upper_limit is None and self.path != self.path.parent) or (
            self.upper_limit is not None and self.path != self.upper_limit
        ):
            self.grid.options["rowData"].insert(
                0,
                {
                    "name": "📁.. ",
                    "path": str(self.path.parent),
                },
            )
        self.grid.update()

    def handle_double_click(self, e: events.GenericEventArguments) -> None:
        self.path = Path(e.args["data"]["path"])
        if self.path.is_dir():
            self.update_grid()
        else:
            self.submit([str(self.path)])

    async def _handle_ok(self) -> None:
        rows = await self.grid.get_selected_rows()
        self.submit([r["path"] for r in rows])


class LocalSaveDialog(ui.dialog):
    """Save dialog that browses directories and lets the user choose where to save a file."""

    def __init__(
        self,
        source_path: str | Path,
        default_filename: str = "canopy_figure.png",
        directory: str | None = None,
    ) -> None:
        super().__init__()
        self.source_path = Path(source_path)
        self.path = Path(directory or Path.home()).expanduser()
        self.show_hidden_files = False

        with self, ui.card():
            ui.label("Choose where to save").classes("text-base font-semibold")
            self.filename_input = ui.input(
                "Filename",
                value=default_filename,
            ).classes("w-full")
            self.add_drives_toggle()
            self.grid = ui.aggrid(
                {
                    "columnDefs": [{"field": "name", "headerName": "Folder"}],
                    "rowSelection": {"mode": "singleRow"},
                },
                html_columns=[0],
            ).classes("w-96").on("cellDoubleClicked", self.handle_double_click)
            with ui.row().classes("w-full justify-end gap-2"):
                ui.button("Cancel", on_click=self.close).props("outline")
                ui.button("Save", on_click=self._handle_save).props("color=positive")
            self.update_grid()

    def add_drives_toggle(self) -> None:
        _add_drives_toggle(self)

    def update_grid(self) -> None:
        paths = [p for p in self.path.glob("*") if p.is_dir()]
        if not self.show_hidden_files:
            paths = [p for p in paths if not p.name.startswith(".")]
        paths.sort(key=lambda p: p.name.lower())

        self.grid.options["rowData"] = [
            {"name": f"📁 {p.name} ", "path": str(p)} for p in paths
        ]
        if self.path != self.path.parent:
            self.grid.options["rowData"].insert(
                0,
                {"name": "📁.. ", "path": str(self.path.parent)},
            )
        self.grid.update()

    def handle_double_click(self, e: events.GenericEventArguments) -> None:
        self.path = Path(e.args["data"]["path"])
        if self.path.is_dir():
            self.update_grid()

    async def _handle_save(self) -> None:
        default = f"canopy_figure{self.source_path.suffix}"
        filename = self.filename_input.value or default
        if not filename.endswith(self.source_path.suffix):
            filename = f"{Path(filename).stem}{self.source_path.suffix}"
        dest = self.path / filename
        try:
            shutil.copy2(self.source_path, dest)
            self.submit(str(dest))
        except OSError as e:
            ui.notify(f"Could not save: {e}", type="negative")
