"""
Step 14 — Form Keyboard Shortcuts Tests

Tests for Ctrl+Enter (save) and Escape (cancel) shortcuts on form views.
The exercise form is used as the representative form; one test each covers
the session and combo forms to confirm the shortcuts are wired consistently.

- test_ctrl_enter_saves_from_body: Ctrl+Enter with no input focused saves the form
- test_ctrl_enter_saves_from_input: Ctrl+Enter while typing in a field saves the form
- test_ctrl_enter_validates_before_saving: Ctrl+Enter with empty title shows validation error
- test_escape_cancels_from_body: Escape with no input focused navigates back to list
- test_escape_cancels_from_input: Escape while a field is focused navigates back to list
- test_escape_cancel_edit_returns_to_detail: Escape on an edit form returns to detail view
- test_save_button_tooltip_contains_shortcut: Save button title attribute shows Ctrl+Enter hint
- test_ctrl_enter_on_session_form: Ctrl+Enter saves from the session new form
- test_ctrl_enter_on_combo_form: Ctrl+Enter saves from the combo new form
- test_ctrl_enter_on_collection_form: Ctrl+Enter saves from the collection new form
"""
from playwright.sync_api import Page, expect


def _wait_db(page: Page, app_url: str):
    page.goto(app_url)
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )


def _clean_exercises(page: Page):
    page.evaluate(
        """async () => {
            const all = await window.__repos.exercises.getAll();
            for (const ex of all) await window.__repos.exercises.delete(ex.id);
        }"""
    )


def _clean_sessions(page: Page):
    page.evaluate(
        """async () => {
            const all = await window.__repos.sessions.getAll();
            for (const s of all) await window.__repos.sessions.delete(s.id);
        }"""
    )


def _clean_combos(page: Page):
    page.evaluate(
        """async () => {
            const all = await window.__repos.combos.getAll();
            for (const c of all) await window.__repos.combos.delete(c.id);
        }"""
    )


def _clean_collections(page: Page):
    page.evaluate(
        """async () => {
            const all = await window.__repos.collections.getAll();
            for (const c of all) await window.__repos.collections.delete(c.id);
        }"""
    )


def _open_exercise_new_form(page: Page, app_url: str):
    _wait_db(page, app_url)
    _clean_exercises(page)
    page.click('a[href="#/exercises"]')
    page.wait_for_timeout(300)
    page.click('[data-testid="exercise-new-btn"]')
    page.wait_for_selector('[data-testid="exercise-title"]')


def test_ctrl_enter_saves_from_body(page: Page, app_url: str):
    """Ctrl+Enter with focus outside any input saves the form and navigates to detail view."""
    _open_exercise_new_form(page, app_url)
    page.fill('[data-testid="exercise-title"]', "Shortcut Save Test")
    # Move focus away from the input (Escape would cancel the form, so blur instead)
    page.evaluate("document.activeElement.blur()")
    page.keyboard.press("Control+Enter")
    page.wait_for_selector('[data-testid="exercise-detail-title"]', timeout=5000)
    expect(page.locator('[data-testid="exercise-detail-title"]')).to_have_text("Shortcut Save Test")
    _clean_exercises(page)


def test_ctrl_enter_saves_from_input(page: Page, app_url: str):
    """Ctrl+Enter while a text input is focused saves the form."""
    _open_exercise_new_form(page, app_url)
    page.fill('[data-testid="exercise-title"]', "Shortcut From Input")
    # Keep focus inside the title input and press Ctrl+Enter
    page.locator('[data-testid="exercise-title"]').press("Control+Enter")
    page.wait_for_selector('[data-testid="exercise-detail-title"]', timeout=5000)
    expect(page.locator('[data-testid="exercise-detail-title"]')).to_have_text("Shortcut From Input")
    _clean_exercises(page)


def test_ctrl_enter_validates_before_saving(page: Page, app_url: str):
    """Ctrl+Enter with an empty title triggers validation rather than saving."""
    _open_exercise_new_form(page, app_url)
    # Do not fill the title — press Ctrl+Enter immediately
    page.locator('[data-testid="exercise-title"]').press("Control+Enter")
    expect(page.locator('[data-testid="exercise-title-error"]')).to_be_visible()
    # Still on the form
    expect(page.locator('[data-testid="exercise-title"]')).to_be_visible()


def test_escape_cancels_from_body(page: Page, app_url: str):
    """Escape with focus on the page body (no input focused) cancels the form and goes back to the list."""
    _open_exercise_new_form(page, app_url)
    page.fill('[data-testid="exercise-title"]', "Should Not Be Saved")
    # Click outside the form to move focus away from any input
    page.locator("h1").first.click()
    page.keyboard.press("Escape")
    page.wait_for_url("**#/exercises", timeout=5000)
    expect(page.locator('[data-testid="exercise-new-btn"]')).to_be_visible()


def test_escape_cancels_from_input(page: Page, app_url: str):
    """Escape while a text input is focused cancels the form and goes back to the list."""
    _open_exercise_new_form(page, app_url)
    page.fill('[data-testid="exercise-title"]', "Should Not Be Saved Either")
    page.locator('[data-testid="exercise-title"]').press("Escape")
    page.wait_for_url("**#/exercises", timeout=5000)
    expect(page.locator('[data-testid="exercise-new-btn"]')).to_be_visible()


def test_escape_cancel_edit_returns_to_detail(page: Page, app_url: str):
    """Escape on an edit form returns to the detail view, not the list."""
    _wait_db(page, app_url)
    _clean_exercises(page)
    # Create an exercise first
    page.click('a[href="#/exercises"]')
    page.wait_for_timeout(300)
    page.click('[data-testid="exercise-new-btn"]')
    page.wait_for_selector('[data-testid="exercise-title"]')
    page.fill('[data-testid="exercise-title"]', "Edit Escape Test")
    page.click('[data-testid="exercise-save"]')
    page.wait_for_selector('[data-testid="exercise-detail-title"]', timeout=5000)
    # Open the edit form
    page.click('[data-testid="exercise-edit-btn"]')
    page.wait_for_selector('[data-testid="exercise-title"]')
    # Press Escape — should go back to the detail view, not the list
    page.keyboard.press("Escape")
    page.wait_for_selector('[data-testid="exercise-detail-title"]', timeout=5000)
    expect(page.locator('[data-testid="exercise-detail-title"]')).to_have_text("Edit Escape Test")
    _clean_exercises(page)


def test_save_button_tooltip_contains_shortcut(page: Page, app_url: str):
    """The save button has a title attribute that includes 'Ctrl+Enter'."""
    _open_exercise_new_form(page, app_url)
    title_attr = page.locator('[data-testid="exercise-save"]').get_attribute("title")
    assert title_attr is not None, "Save button should have a title attribute"
    assert "Ctrl+Enter" in title_attr or "Ctrl+Entrée" in title_attr, (
        f"Expected Ctrl+Enter hint in title, got: {title_attr}"
    )


def test_ctrl_enter_on_session_form(page: Page, app_url: str):
    """Ctrl+Enter saves the session new form from within the title input."""
    _wait_db(page, app_url)
    _clean_sessions(page)
    page.click('a[href="#/sessions"]')
    page.wait_for_timeout(300)
    page.click('[data-testid="session-new-btn"]')
    page.wait_for_selector('[data-testid="session-title"]')
    page.fill('[data-testid="session-title"]', "Session Shortcut Test")
    page.locator('[data-testid="session-title"]').press("Control+Enter")
    page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000)
    expect(page.locator('[data-testid="session-detail-title"]')).to_have_text("Session Shortcut Test")
    _clean_sessions(page)


def test_ctrl_enter_on_combo_form(page: Page, app_url: str):
    """Ctrl+Enter saves the combo new form from within the title input."""
    _wait_db(page, app_url)
    _clean_combos(page)
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(300)
    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')
    page.fill('[data-testid="combo-title"]', "Combo Shortcut Test")
    page.locator('[data-testid="combo-title"]').press("Control+Enter")
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)
    expect(page.locator('[data-testid="combo-detail-title"]')).to_have_text("Combo Shortcut Test")
    _clean_combos(page)


def test_ctrl_enter_on_collection_form(page: Page, app_url: str):
    """Ctrl+Enter saves the collection new form from within the label input."""
    _wait_db(page, app_url)
    _clean_collections(page)
    page.click('a[href="#/collections"]')
    page.wait_for_timeout(300)
    page.click('[data-testid="collection-new-btn"]')
    page.wait_for_selector('[data-testid="collection-label"]')
    page.fill('[data-testid="collection-label"]', "Collection Shortcut Test")
    page.locator('[data-testid="collection-label"]').press("Control+Enter")
    page.wait_for_selector('[data-testid="collection-detail-title"]', timeout=5000)
    expect(page.locator('[data-testid="collection-detail-title"]')).to_have_text("Collection Shortcut Test")
    _clean_collections(page)
