"""Main Textual application for Lettera."""

from pathlib import Path
from typing import List
from textual.app import App, ComposeResult
from textual.screen import Screen
from textual.widgets import Footer, Header
from textual.containers import Container, Vertical
from textual.binding import Binding
from textual.reactive import reactive
from textual import work

from .service import Service
from .widgets.editor import TypewriterEditor
from .widgets.header import HeaderBar
from .widgets.fade import FadeOverlay
from .widgets.archive import ArchiveList
from .types import EntryMeta


class EditorScreen(Screen):
    """Main editor screen."""

    BINDINGS = [
        Binding("ctrl+x", "strikethrough", "Strike", priority=True),
        Binding("ctrl+s", "save", "Save", priority=True),
        Binding("ctrl+n", "new_page", "New", priority=True),
        Binding("ctrl+o", "open_archive", "Archive", priority=True),
        Binding("ctrl+q", "quit_app", "Quit", priority=True),
    ]

    current_file = reactive(None)

    def __init__(self, service: Service, *args, **kwargs):
        """Initialize editor screen."""
        super().__init__(*args, **kwargs)
        self.service = service

    def compose(self) -> ComposeResult:
        """Compose the editor screen."""
        yield HeaderBar(id="header")
        yield TypewriterEditor(id="editor")
        yield Footer()
        yield FadeOverlay(id="fade")

    async def on_mount(self) -> None:
        """Set up the editor when mounted."""
        # Create a new entry file path for the initial session
        self.current_file = self.service.create_entry_path()

    async def action_strikethrough(self) -> None:
        """Apply strikethrough to character at cursor (Ctrl+X)."""
        editor = self.query_one("#editor", TypewriterEditor)
        editor._apply_strikethrough()

    async def action_save(self) -> None:
        """Save current entry (Ctrl+S)."""
        editor = self.query_one("#editor", TypewriterEditor)

        if not editor.has_unsaved_changes:
            # Nothing to save, but still show closure ritual
            await self._trigger_closure_ritual()
            return

        content = editor.text

        if not content.strip():
            # Don't save empty files
            return

        # Save the entry
        await self.service.save_entry(self.current_file, content)
        editor.has_unsaved_changes = False

        # Trigger closure ritual
        await self._trigger_closure_ritual()

    async def action_new_page(self) -> None:
        """Create a new page (Ctrl+N)."""
        editor = self.query_one("#editor", TypewriterEditor)

        # Clear the editor
        editor.clear_content()

        # Create new entry file path
        self.current_file = self.service.create_entry_path()

    @work
    async def action_open_archive(self) -> None:
        """Open archive screen (Ctrl+O)."""
        entries = await self.service.list_entries()
        archive_screen = ArchiveScreen(self.service, entries)
        entry = await self.app.push_screen_wait(archive_screen)
        if entry is not None:
            await self.load_entry(entry)

    async def action_quit_app(self) -> None:
        """Quit the application (Ctrl+Q)."""
        # Show closure ritual before quitting
        fade = self.query_one("#fade", FadeOverlay)
        await fade.animate()
        self.app.exit()

    async def _trigger_closure_ritual(self) -> None:
        """Trigger the fade-to-black closure ritual."""
        fade = self.query_one("#fade", FadeOverlay)
        await fade.animate()

    async def load_entry(self, entry: EntryMeta) -> None:
        """Load an entry from the archive."""
        try:
            content = await self.service.load_entry(entry.path)
            editor = self.query_one("#editor", TypewriterEditor)
            editor.load_content(content)
            self.current_file = entry.path
        except Exception as e:
            # Log error but don't crash
            self.app.log(f"Error loading entry: {e}")


class ArchiveScreen(Screen):
    """Archive browsing screen."""

    BINDINGS = [
        Binding("escape", "back_to_editor", "Back", priority=True),
    ]

    def __init__(self, service: Service, entries: List[EntryMeta], *args, **kwargs):
        """Initialize archive screen."""
        super().__init__(*args, **kwargs)
        self.service = service
        self.entries = entries

    def compose(self) -> ComposeResult:
        """Compose the archive screen."""
        yield HeaderBar(id="header")
        with Vertical():
            yield ArchiveList(self.entries, id="archive")
        yield Footer()

    async def on_archive_list_entry_selected(
        self, event: ArchiveList.EntrySelected
    ) -> None:
        """Handle entry selection from archive."""
        self.dismiss(event.entry)

    async def action_back_to_editor(self) -> None:
        """Return to editor (Esc)."""
        self.dismiss(None)


class LetteraApp(App):
    """Lettera typewriter journaling application."""

    CSS = """
    Screen {
        background: #1a1a1a;
    }

    #header {
        dock: top;
        height: 3;
        background: #242424;
        color: #4a9eff;
        content-align: center middle;
        text-style: bold;
    }

    #editor {
        background: #1a1a1a;
        color: #e0e0e0;
        border: none;
        padding: 2 4;
    }

    Footer {
        background: #242424;
    }

    Footer .footer--key {
        color: #4a9eff;
    }

    Footer .footer--description {
        color: #888888;
    }

    #archive {
        background: #1a1a1a;
        border: solid #4a9eff;
        height: 100%;
    }

    #archive > ListItem {
        padding: 1 2;
    }

    #archive > ListItem:hover {
        background: #242424;
    }

    #archive > ListItem.empty {
        color: #666666;
        text-style: italic;
    }

    FadeOverlay {
        background: black;
    }
    """

    def __init__(self):
        """Initialize the Lettera app."""
        super().__init__()
        self.service = Service()

    def on_mount(self) -> None:
        """Set up the app when mounted."""
        # Push the editor screen as the initial screen
        self.push_screen(EditorScreen(self.service))
