"""
Step 4 — Combo Management Tests
- test_combo_list_empty: Shows empty state when no combos exist
- test_create_combo_minimal: Create combo with only required field (title)
- test_create_combo_full: Create combo with all fields including exercises
- test_combo_appears_in_list: Created combo appears in the list with badges
- test_combo_detail_view: Detail view shows all combo data
- test_edit_combo: Edit a combo and verify changes
- test_delete_combo: Delete a combo with confirmation
- test_delete_combo_cancel: Cancelling delete does not remove combo
- test_delete_combo_used_in_session: Delete confirm mentions usage; no session_item orphans
- test_search_combos: Search filters combos by title
- test_search_no_results: Search with no matches shows empty message
- test_search_clear_button: Clear button empties the search field and restores the full list
- test_validation_title_required: Empty title shows validation error
- test_duplicate_title_rejected: Creating combo with duplicate title shows error
- test_reorder_exercises: Reorder exercises in combo
- test_remove_exercise: Remove an exercise from combo
- test_type_change: Changing type shows/hides timer config fields
- test_action_bar_buttons: New and Search buttons appear in action bar
"""
from playwright.sync_api import Page, expect


def _wait_for_db(page: Page, app_url: str):
    """Navigate and wait for the database to be ready."""
    page.goto(app_url)
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )


def _go_to_combos(page: Page, app_url: str):
    """Navigate to the combos list and wait for it to load."""
    _wait_for_db(page, app_url)
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)


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


def _create_exercise_via_repo(page: Page, title):
    """Create an exercise via the repository and return its ID."""
    return page.evaluate(
        """async (title) => {
            const uuid = await window.__repos.settings.get('user_uuid');
            return window.__repos.exercises.create({
                title: title, description: '', asymmetric: false, alternate: false,
                image_urls: [], video_urls: [], default_reps: 10, default_weight: 0,
                created_by: uuid
            });
        }""",
        title,
    )


def _create_combo_via_ui(page: Page, title, description="", combo_type="NONE", exercise_ids=None):
    """Fill the combo form and save via UI."""
    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    page.fill('[data-testid="combo-title"]', title)

    if description:
        page.fill('[data-testid="combo-description"]', description)

    if combo_type != "NONE":
        page.select_option('[data-testid="combo-type"]', combo_type)

    if exercise_ids:
        for ex_id in exercise_ids:
            page.select_option('[data-testid="combo-exercise-select"]', ex_id)
            page.click('[data-testid="combo-exercise-add"]')

    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)


def test_combo_list_empty(page: Page, app_url: str):
    """Empty state is shown when no combos exist."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)
    expect(page.locator('[data-testid="combo-empty"]')).to_be_visible()


def test_create_combo_minimal(page: Page, app_url: str):
    """Create a combo with only the required title field."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(page, "My First Combo")

    expect(page.locator('[data-testid="combo-detail-title"]')).to_have_text("My First Combo")

    _clean_combos(page)


def test_create_combo_full(page: Page, app_url: str):
    """Create a combo with all fields including exercises."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    # Create exercises first
    ex1_id = _create_exercise_via_repo(page, "Push-ups")
    ex2_id = _create_exercise_via_repo(page, "Squats")

    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(
        page,
        title="Upper Body Blast",
        description="Quick combo for upper body",
        combo_type="EMOM",
        exercise_ids=[ex1_id, ex2_id],
    )

    expect(page.locator('[data-testid="combo-detail-title"]')).to_have_text("Upper Body Blast")
    expect(page.locator('[data-testid="combo-detail-description"]')).to_have_text(
        "Quick combo for upper body"
    )
    expect(page.locator('[data-testid="combo-detail-type"]')).to_have_text("EMOM")
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("Push-ups")
    expect(page.locator('[data-testid="combo-detail-exercise-1"]')).to_contain_text("Squats")

    _clean_combos(page)


def test_combo_appears_in_list(page: Page, app_url: str):
    """Created combo appears in the list view with correct info."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(page, title="Test Combo", combo_type="AMRAP")

    page.click('[data-testid="combo-back-btn"]')
    page.wait_for_timeout(500)

    card_title = page.locator('[data-testid="combo-card-title"]')
    expect(card_title.first).to_have_text("Test Combo")
    expect(page.locator('[data-testid="combo-card-type"]').first).to_have_text("AMRAP")

    _clean_combos(page)


def test_combo_detail_view(page: Page, app_url: str):
    """Detail view shows all combo data correctly."""
    _go_to_combos(page, app_url)
    _clean_combos(page)

    # Create exercise first
    ex_id = _create_exercise_via_repo(page, "Burpees")

    # Create combo via repo
    combo_id = page.evaluate(
        """async ({ exId }) => {
            const uuid = await window.__repos.settings.get('user_uuid');
            const id = await window.__repos.combos.create({
                title: 'HIIT Combo',
                description: 'High intensity interval training',
                type: 'TABATA',
                timer_config: { rounds: 8 },
                created_by: uuid
            });
            await window.__repos.combos.setExercises(id, [exId]);
            return id;
        }""",
        {"exId": ex_id},
    )

    page.goto(f"{app_url}/#/combos/{combo_id}")
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    expect(page.locator('[data-testid="combo-detail-title"]')).to_have_text("HIIT Combo")
    expect(page.locator('[data-testid="combo-detail-description"]')).to_have_text(
        "High intensity interval training"
    )
    expect(page.locator('[data-testid="combo-detail-type"]')).to_have_text("TABATA")
    expect(page.locator('[data-testid="combo-detail-tabata-rounds"]')).to_contain_text("8")

    _clean_combos(page)


def test_edit_combo(page: Page, app_url: str):
    """Edit a combo and verify changes are persisted."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(page, title="Original Combo", combo_type="NONE")

    page.click('[data-testid="combo-edit-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    page.fill('[data-testid="combo-title"]', "Updated Combo")
    page.select_option('[data-testid="combo-type"]', "EMOM")
    page.fill('[data-testid="combo-emom-duration"]', "15")

    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    expect(page.locator('[data-testid="combo-detail-title"]')).to_have_text("Updated Combo")
    expect(page.locator('[data-testid="combo-detail-type"]')).to_have_text("EMOM")

    _clean_combos(page)


def test_delete_combo(page: Page, app_url: str):
    """Delete a combo with confirmation dialog."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(page, title="To Delete")

    page.on("dialog", lambda dialog: dialog.accept())
    page.click('[data-testid="combo-delete-btn"]')
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-empty"]')).to_be_visible()


def test_delete_combo_cancel(page: Page, app_url: str):
    """Cancelling the delete dialog does not remove the combo."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(page, title="Keep Me")

    page.on("dialog", lambda dialog: dialog.dismiss())
    page.click('[data-testid="combo-delete-btn"]')
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-detail-title"]')).to_have_text("Keep Me")

    _clean_combos(page)


def test_delete_combo_used_in_session(page: Page, app_url: str):
    """Deleting a combo used in a session warns about the usage, and after
    deletion no session_item rows reference it (no orphans)."""
    _go_to_combos(page, app_url)
    _clean_combos(page)

    ex_id = _create_exercise_via_repo(page, "Combo Member Exercise")
    combo_id = page.evaluate(
        f"""async () => {{
            const uuid = await window.__repos.settings.get('user_uuid');
            const comboId = await window.__repos.combos.create({{
                title: 'Combo In Session', description: '', type: 'NONE', created_by: uuid
            }});
            await window.__repos.combos.setExercises(comboId, ['{ex_id}']);
            const sessionId = await window.__repos.sessions.create({{
                title: 'Session Using Combo', description: '', created_by: uuid
            }});
            await window.__repos.sessions.setItems(sessionId, [
                {{ item_id: comboId, item_type: 'combo', repetitions: 1, weight: 0 }},
            ]);
            return comboId;
        }}"""
    )

    dialog_message = {}

    def on_dialog(dialog):
        dialog_message["text"] = dialog.message
        dialog.accept()

    page.on("dialog", on_dialog)

    page.goto(f"{app_url}/#/combos/{combo_id}")
    page.wait_for_selector('[data-testid="combo-delete-btn"]', timeout=5000)
    page.click('[data-testid="combo-delete-btn"]')
    page.wait_for_timeout(500)

    msg = dialog_message.get("text", "")
    assert "1 session(s)" in msg, f"Confirm must mention session usage, got: {msg}"

    orphans = page.evaluate(
        f"""async () => (await window.__db.selectAll(
            "SELECT * FROM session_item WHERE item_id = '{combo_id}'"
        )).length"""
    )
    assert orphans == 0, f"Expected no orphaned session_item rows, got {orphans}"

    # Clean up the seeded session and exercise
    page.evaluate(
        """async () => {
            for (const s of await window.__repos.sessions.getAll())
                await window.__repos.sessions.delete(s.id)
            for (const e of await window.__repos.exercises.getAll())
                await window.__repos.exercises.delete(e.id)
        }"""
    )


def test_search_combos(page: Page, app_url: str):
    """Search filters combos by title."""
    _go_to_combos(page, app_url)
    _clean_combos(page)

    # Create multiple combos via repo
    page.evaluate(
        """async () => {
            const uuid = await window.__repos.settings.get('user_uuid');
            await window.__repos.combos.create({
                title: 'Upper Body', description: '', type: 'EMOM',
                timer_config: {}, created_by: uuid
            });
            await window.__repos.combos.create({
                title: 'Lower Body', description: '', type: 'AMRAP',
                timer_config: {}, created_by: uuid
            });
            await window.__repos.combos.create({
                title: 'Full Body', description: '', type: 'TABATA',
                timer_config: {}, created_by: uuid
            });
        }"""
    )

    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-card-title"]')).to_have_count(3)

    page.click('[data-testid="combo-search-toggle"]')
    page.wait_for_selector('[data-testid="combo-search-input"]')

    page.fill('[data-testid="combo-search-input"]', "Body")
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-card-title"]')).to_have_count(3)

    page.fill('[data-testid="combo-search-input"]', "Upper")
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-card-title"]')).to_have_count(1)
    expect(page.locator('[data-testid="combo-card-title"]')).to_have_text("Upper Body")

    _clean_combos(page)


def test_search_no_results(page: Page, app_url: str):
    """Search with no matches shows no-results message."""
    _go_to_combos(page, app_url)
    _clean_combos(page)

    page.evaluate(
        """async () => {
            const uuid = await window.__repos.settings.get('user_uuid');
            await window.__repos.combos.create({
                title: 'Upper Body', description: '', type: 'EMOM',
                timer_config: {}, created_by: uuid
            });
        }"""
    )

    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    page.click('[data-testid="combo-search-toggle"]')
    page.fill('[data-testid="combo-search-input"]', "zzzznotfound")
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-no-results"]')).to_be_visible()

    _clean_combos(page)


def test_search_clear_button(page: Page, app_url: str):
    """Clear button empties the search field and restores the full list."""
    _go_to_combos(page, app_url)
    _clean_combos(page)

    page.evaluate(
        """async () => {
            const uuid = await window.__repos.settings.get('user_uuid');
            await window.__repos.combos.create({
                title: 'Upper Body', description: '', type: 'EMOM',
                timer_config: {}, created_by: uuid
            });
            await window.__repos.combos.create({
                title: 'Lower Body', description: '', type: 'AMRAP',
                timer_config: {}, created_by: uuid
            });
        }"""
    )

    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    page.click('[data-testid="combo-search-toggle"]')

    expect(page.locator('[data-testid="combo-search-clear"]')).not_to_be_visible()

    page.fill('[data-testid="combo-search-input"]', "Upper")
    page.wait_for_timeout(500)
    expect(page.locator('[data-testid="combo-card-title"]')).to_have_count(1)

    page.click('[data-testid="combo-search-clear"]')
    expect(page.locator('[data-testid="combo-search-input"]')).to_have_value("")
    page.wait_for_timeout(500)
    expect(page.locator('[data-testid="combo-card-title"]')).to_have_count(2)

    expect(page.locator('[data-testid="combo-search-input"]')).to_be_focused()

    _clean_combos(page)


def test_validation_title_required(page: Page, app_url: str):
    """Empty title shows validation error and prevents save."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    page.click('[data-testid="combo-save"]')

    expect(page.locator('[data-testid="combo-title-error"]')).to_be_visible()
    expect(page.locator('[data-testid="combo-title"]')).to_be_visible()


def test_duplicate_title_rejected(page: Page, app_url: str):
    """Creating a combo with a duplicate title shows an error."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(page, title="Unique Combo")

    page.click('[data-testid="combo-back-btn"]')
    page.wait_for_timeout(500)

    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')
    page.fill('[data-testid="combo-title"]', "Unique Combo")
    page.click('[data-testid="combo-save"]')
    page.wait_for_timeout(500)

    title_error_visible = page.locator('[data-testid="combo-title-error"]').is_visible()
    save_error_visible = page.locator('[data-testid="combo-save-error"]').is_visible()
    assert title_error_visible or save_error_visible, "Expected duplicate title error"

    _clean_combos(page)


def test_reorder_exercises(page: Page, app_url: str):
    """Reorder exercises in a combo."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    # Create exercises
    ex1_id = _create_exercise_via_repo(page, "Push-ups")
    ex2_id = _create_exercise_via_repo(page, "Squats")
    ex3_id = _create_exercise_via_repo(page, "Burpees")

    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    # Create combo with 3 exercises
    _create_combo_via_ui(
        page,
        title="Reorder Test",
        exercise_ids=[ex1_id, ex2_id, ex3_id],
    )

    # Go to edit
    page.click('[data-testid="combo-edit-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    # Move Squats (index 1) up
    page.click('[data-testid="combo-exercise-move-up-1"]')

    # Save
    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    # Verify order: Squats, Push-ups, Burpees
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("Squats")
    expect(page.locator('[data-testid="combo-detail-exercise-1"]')).to_contain_text("Push-ups")
    expect(page.locator('[data-testid="combo-detail-exercise-2"]')).to_contain_text("Burpees")

    _clean_combos(page)


def test_remove_exercise(page: Page, app_url: str):
    """Remove an exercise from a combo."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    ex1_id = _create_exercise_via_repo(page, "Push-ups")
    ex2_id = _create_exercise_via_repo(page, "Squats")

    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    _create_combo_via_ui(
        page,
        title="Remove Test",
        exercise_ids=[ex1_id, ex2_id],
    )

    page.click('[data-testid="combo-edit-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    # Remove first exercise
    page.click('[data-testid="combo-exercise-remove-0"]')

    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    # Only Squats should remain
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("Squats")
    expect(page.locator('[data-testid="combo-detail-exercise-1"]')).not_to_be_attached()

    _clean_combos(page)


def test_type_change(page: Page, app_url: str):
    """Changing type shows/hides timer config fields."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    # NONE type: no timer config fields
    expect(page.locator('[data-testid="combo-emom-duration"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-amrap-duration"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-tabata-work-time"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-tabata-rest-time"]')).not_to_be_visible()

    # Switch to EMOM
    page.select_option('[data-testid="combo-type"]', "EMOM")
    expect(page.locator('[data-testid="combo-emom-duration"]')).to_be_visible()
    expect(page.locator('[data-testid="combo-amrap-duration"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-tabata-work-time"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-tabata-rest-time"]')).not_to_be_visible()

    # Switch to TABATA
    page.select_option('[data-testid="combo-type"]', "TABATA")
    expect(page.locator('[data-testid="combo-emom-duration"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-amrap-duration"]')).not_to_be_visible()
    expect(page.locator('[data-testid="combo-tabata-work-time"]')).to_be_visible()
    expect(page.locator('[data-testid="combo-tabata-rest-time"]')).to_be_visible()

    _clean_combos(page)


def test_action_bar_buttons(page: Page, app_url: str):
    """New and Search buttons are visible in the action bar on the combo list."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    expect(page.locator('[data-testid="combo-new-btn"]')).to_be_visible()
    expect(page.locator('[data-testid="combo-search-toggle"]')).to_be_visible()


def test_create_combo_with_reps_and_weight(page: Page, app_url: str):
    """Create combo with exercises and set reps/weight values."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    # Create exercises
    ex1_id = _create_exercise_via_repo(page, "Push-ups")
    ex2_id = _create_exercise_via_repo(page, "Squats")

    # Create combo with exercises
    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    page.fill('[data-testid="combo-title"]', "Reps Weight Test")

    # Add first exercise
    page.select_option('[data-testid="combo-exercise-select"]', ex1_id)
    page.click('[data-testid="combo-exercise-add"]')

    # Add second exercise
    page.select_option('[data-testid="combo-exercise-select"]', ex2_id)
    page.click('[data-testid="combo-exercise-add"]')

    # Set reps and weight for first exercise
    page.fill('[data-testid="combo-exercise-reps-0"]', "12")
    page.fill('[data-testid="combo-exercise-weight-0"]', "50")

    # Set reps for second exercise (weight stays default)
    page.fill('[data-testid="combo-exercise-reps-1"]', "15")

    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    # Verify detail view shows reps and weight
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("Push-ups")
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("12")
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("50")
    expect(page.locator('[data-testid="combo-detail-exercise-1"]')).to_contain_text("Squats")
    expect(page.locator('[data-testid="combo-detail-exercise-1"]')).to_contain_text("15")

    _clean_combos(page)


def test_edit_combo_reps_and_weight(page: Page, app_url: str):
    """Edit combo and change reps/weight values."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    # Create exercise
    ex_id = _create_exercise_via_repo(page, "Deadlifts")

    # Create combo
    _create_combo_via_ui(
        page,
        title="Edit Reps Weight Test",
        exercise_ids=[ex_id],
    )

    # Edit combo
    page.click('[data-testid="combo-edit-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    # Change reps and weight
    page.fill('[data-testid="combo-exercise-reps-0"]', "8")
    page.fill('[data-testid="combo-exercise-weight-0"]', "100")

    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    # Verify updated values
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("Deadlifts")
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("8")
    expect(page.locator('[data-testid="combo-detail-exercise-0"]')).to_contain_text("100")

    _clean_combos(page)


def test_reps_weight_defaults(page: Page, app_url: str):
    """Reps prefill from the exercise's default_reps and weight defaults to 0."""
    _go_to_combos(page, app_url)
    _clean_combos(page)
    page.reload()
    page.wait_for_function(
        "document.documentElement.getAttribute('data-db-ready') === 'true'",
        timeout=15000,
    )
    page.click('a[href="#/combos"]')
    page.wait_for_timeout(500)

    # Create exercise
    ex_id = _create_exercise_via_repo(page, "Lunges")

    # Create combo
    page.click('[data-testid="combo-new-btn"]')
    page.wait_for_selector('[data-testid="combo-title"]')

    page.fill('[data-testid="combo-title"]', "Defaults Test")

    # Add exercise
    page.select_option('[data-testid="combo-exercise-select"]', ex_id)
    page.click('[data-testid="combo-exercise-add"]')

    # Verify default values in inputs (_create_exercise_via_repo sets default_reps=10)
    reps_input = page.locator('[data-testid="combo-exercise-reps-0"]')
    weight_input = page.locator('[data-testid="combo-exercise-weight-0"]')
    expect(reps_input).to_have_value("10")
    expect(weight_input).to_have_value("0")

    # Save without changing
    page.click('[data-testid="combo-save"]')
    page.wait_for_selector('[data-testid="combo-detail-title"]', timeout=5000)

    # Verify defaults are shown in detail view (always shown now)
    exercise_item = page.locator('[data-testid="combo-detail-exercise-0"]')
    expect(exercise_item).to_contain_text("Lunges")
    expect(page.locator('[data-testid="combo-detail-exercise-details-0"]')).to_contain_text("10")
    expect(page.locator('[data-testid="combo-detail-exercise-details-0"]')).to_contain_text("0")

    _clean_combos(page)
