import os

from textual import on
from textual.app import App
from textual.binding import Binding
from textual.containers import Container, Horizontal, Vertical
from textual.widgets import (
    Button,
    Footer,
    Input,
    Label,
    ListItem,
    ListView,
    Markdown,
    Switch,
)

from carabao.cli.cmd_new.item import Item


class Display(App):
    default_lane_name: str = "MyLane"
    default_lane_directory: str = "lanes"

    BINDINGS = [
        Binding("escape", "exit_app", "Exit", priority=True),
        Binding("enter", "run_lane", "Run", priority=True),
    ]

    CSS_PATH = os.path.join(
        os.path.dirname(__file__),
        "display.tcss",
    )

    SAMPLES_FOLDERPATH = os.path.normpath(
        os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            "../sample",
        )
    )
    TEMPLATES = sorted(
        [
            {
                "name": "Basic Lane",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "basic.py",
                ),
                "description": "A simple lane that processes data sequentially.",
            },
            {
                "name": "Factory Lane",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "factory.py",
                ),
                "description": "A factory pattern implementation for lane processing.",
            },
            {
                "name": "Passive Lane",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "passive.py",
                ),
                "description": "A lane that runs in the background.",
            },
            {
                "name": "Subscriber Lane",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "subscriber.py",
                ),
                "description": "A lane that implements the publisher-subscriber pattern to receive events.",
            },
            {
                "name": "Branching Lane",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "branching.py",
                ),
                "description": "A lane that branches to multiple lanes based on the input.",
            },
            {
                "name": "Batched Subscriber Lane",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "batched_subscriber.py",
                ),
                "description": "A lane that processes data in batches.",
            },
            {
                "name": "Lane with Form",
                "file": os.path.join(
                    SAMPLES_FOLDERPATH,
                    "form.py",
                ),
                "description": "A lane that has a form.",
            },
        ],
        key=lambda x: x["name"],
    )

    def compose(self):
        yield Footer()

        with Vertical():
            with Horizontal():
                # Create ListView with template names
                self.template_list = ListView(
                    *(ListItem(Label(template["name"])) for template in self.TEMPLATES),
                    id="template-list",
                )

                yield self.template_list

                # Vertical container for inputs and info
                with Vertical(id="right-container"):
                    # Text inputs section
                    with Container(id="inputs-container"):
                        yield Label(
                            "Name",
                            classes="input-label",
                        )

                        self.name_input = Input(
                            placeholder=self.default_lane_name,
                            id="name-input",
                        )

                        yield self.name_input

                        yield Label(
                            "Directory",
                            classes="input-label",
                        )

                        self.directory_input = Input(
                            placeholder=self.default_lane_directory,
                        )

                        yield self.directory_input

                        with Horizontal(
                            classes="switch",
                        ):
                            self.use_filename = Switch(
                                True,
                                id="use-filename",
                            )
                            yield self.use_filename
                            yield Label("Use Filename as Name?")

                    # Container for template content
                    with Container(id="info-container"):
                        yield Label(
                            "Description",
                            classes="info-label",
                        )

                        self.description_widget = Label(
                            "",
                            classes="info-widget",
                        )

                        yield self.description_widget
                        yield Label(
                            "Content Preview",
                            classes="info-label",
                        )

                        self.content_widget = Markdown(
                            "",
                            id="content",
                            classes="info-widget",
                        )

                        yield self.content_widget

            # Container for action buttons at bottom
            with Horizontal(id="navi-container"):
                yield Button.success(
                    "\\[Enter] Create",
                    id="select",
                )

                yield Button.error(
                    "\\[Esc] Cancel",
                    id="exit",
                )

        self.update(0)

    def update(self, index: int):
        self.update_item(index)
        self.update_info(index)

    def update_item(self, index: int):
        template = self.TEMPLATES[index]

        with open(template["file"], "r") as f:
            content = f.read()

        lane_name = self.name_input.value or self.default_lane_name

        if not self.use_filename.value:
            content = content.replace(
                "class Main(Lane):",
                f"class {lane_name}(Lane):",
            ).replace(
                "use_filename: bool = True",
                "use_filename: bool = False",
            )

        self.__item = Item(
            lane_name=lane_name,
            lane_directory=self.directory_input.value or self.default_lane_directory,
            use_filename=self.use_filename.value,
            content=content,
        )

    def update_info(self, index: int):
        template = self.TEMPLATES[index]

        self.description_widget.update(template["description"])

        try:
            content = self.__item.content.replace(
                "[",
                "\\[",
            ).replace(
                "]",
                "\\]",
            )

            self.content_widget.update(
                f"```py\n{content}\n```",
            )
        except Exception:
            self.content_widget.update(
                "Could not load template content.",
            )

    def action_exit_app(self):
        self.on_exit()

    def action_run_lane(self):
        self.on_select()

    @on(Input.Changed)
    def on_name_input_changed(self, event: Input.Changed):
        self.update(self.template_list.index or 0)

    @on(Switch.Changed)
    def on_use_filename_changed(self):
        self.update(self.template_list.index or 0)

    @on(Button.Pressed, "#exit")
    def on_exit(self):
        self.exit(None)

    @on(ListView.Highlighted, "#template-list")
    def on_template_selected(self, event: ListView.Selected):
        self.update(event.list_view.index or 0)

    @on(Button.Pressed, "#select")
    def on_select(self):
        self.exit(self.__item)
