# Implementation Plan: Profile Edit Collapsible

## Overview

This plan fixes the missing persistent edit UI for height and gender on the Track Visceral Fat screen. Once a user sets their height/gender via the one-time prompts, those prompts disappear and no alternative UI exists to view or modify the saved values. The fix adds an always-visible collapsible `ExpansionTile` "Height & Gender" section that provides ongoing access to view and edit profile data.

The implementation follows the exploratory bugfix workflow: write tests to confirm the bug exists, write preservation tests to protect existing behavior, then implement the fix and verify both test suites pass.

## Tasks

- [x] 1. Write bug condition exploration test
  - **Property 1: Bug Condition** - No Edit UI Available When Profile Values Are Set
  - **CRITICAL**: This test MUST FAIL on unfixed code - failure confirms the bug exists
  - **DO NOT attempt to fix the test or the code when it fails**
  - **NOTE**: This test encodes the expected behavior - it will validate the fix when it passes after implementation
  - **GOAL**: Surface counterexamples that demonstrate once height/gender are saved, no edit UI is accessible
  - **Scoped PBT Approach**: Scope the property to concrete failing cases — render `TrackVisceralFatScreen` with a pre-populated `UserProfile` (height and/or gender set) and assert that an `ExpansionTile` with "Height & Gender" title exists in the widget tree
  - Create a widget test in `test/property_tests/` that:
    - Mounts `TrackVisceralFatScreen` with a mocked `HealthDataBloc` emitting `HealthDataLoaded` state containing a `UserProfile` with height and gender set
    - Asserts that an `ExpansionTile` widget with title text "Height & Gender" is found in the widget tree
    - Asserts that when expanded, height value/unit and gender value are displayed
    - Asserts that edit controls (height input, gender chips, save button) are accessible within the expanded section
  - Use `glados` to generate random `UserProfile` states (various combinations of non-null height values in valid range 50-275 cm, height units 'cm'/'inches', genders 'male'/'female') and verify the collapsible section is always present
  - Run test on UNFIXED code
  - **EXPECTED OUTCOME**: Test FAILS (no `ExpansionTile` with "Height & Gender" exists — this proves the bug: once values are set, no edit UI is available)
  - Document counterexamples: "For any UserProfile with heightValue=175, heightUnit='cm', gender='male', no ExpansionTile or edit UI is rendered on the screen"
  - Mark task complete when test is written, run, and failure is documented
  - _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 2.3_

- [x] 2. Write preservation property tests (BEFORE implementing fix)
  - **Property 2: Preservation** - One-Time Prompts and Form Behavior Unchanged
  - **IMPORTANT**: Follow observation-first methodology
  - Observe on UNFIXED code:
    - Render with null height/gender → one-time height prompt appears with "Set Your Height" title, close button, height input field, unit dropdown, and "Save Height" button
    - Render with null gender → one-time gender prompt appears with "Set Your Gender" title, close button, Male/Female choice chips, and "Save Gender" button
    - Tap close button on height prompt → prompt disappears for the session (`_heightPromptDismissed = true`)
    - Tap close button on gender prompt → prompt disappears for the session (`_genderPromptDismissed = true`)
    - Submit valid waist measurement → `AddWaistEntryEvent` dispatched, success snackbar appears, screen navigates back
    - Save height via prompt → success snackbar "Height saved" appears with green background
    - Save gender via prompt → success snackbar "Gender saved" appears with green background
  - Write property-based tests capturing observed behavior:
    - **One-time height prompt**: For any `UserProfile` with null `heightValue`, the height prompt card with "Set Your Height" title is visible
    - **One-time gender prompt**: For any `UserProfile` with null `gender`, the gender prompt card with "Set Your Gender" title is visible
    - **Prompt dismissal**: Tapping close button on height/gender prompt hides it for the session
    - **Waist form submission**: For any valid waist value (30-300 cm range), submitting the form dispatches `AddWaistEntryEvent`
    - **Profile save snackbars**: Saving height/gender via one-time prompts shows respective success snackbars
  - Use `glados` to generate random valid waist values and profile states for stronger guarantees
  - Verify all tests PASS on UNFIXED code (these behaviors already work correctly)
  - **EXPECTED OUTCOME**: Tests PASS (confirms baseline behavior to preserve)
  - Mark task complete when tests are written, run, and passing on unfixed code
  - _Requirements: 3.1, 3.2, 3.3, 3.4, 3.5_

- [x] 3. Fix missing profile edit UI on TrackVisceralFatScreen

  - [x] 3.1 Implement the fix
    - Add new state variables for the collapsible section: `_editingHeight` (double?), `_editingHeightUnit` (String), `_editingGender` (String?) — separate from one-time prompt state to avoid interference
    - Create `_buildProfileEditSection(ThemeData theme, UserProfile? userProfile)` method that returns a `Card` wrapping an `ExpansionTile` with:
      - Title text: "Height & Gender"
      - `initiallyExpanded: false` (collapsed by default)
      - Leading icon: `Icons.person_outline`
      - Children: height display/edit (ValidatedNumberField + unit dropdown), gender display/edit (ChoiceChip for Male/Female), and a "Save Changes" ElevatedButton
    - Populate edit fields from `userProfile` values when the section expands (or on initial build)
    - Display "Not set" when height/gender values are null
    - Save button dispatches `SaveUserProfileEvent` with updated `UserProfile` and shows success snackbar
    - Insert `_buildProfileEditSection` in the `Column` children after the Notes card and before the one-time prompts:
      ```
      _buildNotesCard(theme),
      SizedBox(height: 16),
      _buildProfileEditSection(theme, userProfile),  // NEW
      SizedBox(height: 16),
      // existing one-time prompts (unchanged)
      ```
    - Reuse existing `_validateHeight` for height validation in the collapsible section
    - Do NOT modify one-time prompt logic (`_buildHeightPrompt`, `_buildGenderPrompt`) — those remain unchanged
    - _Bug_Condition: isBugCondition(input) where (input.userProfile.hasHeight OR input.userProfile.hasGender) AND screenState == 'track_visceral_fat_screen_displayed' AND NOT editUIAvailable(input.userProfile)_
    - _Expected_Behavior: An always-visible collapsible "Height & Gender" ExpansionTile is rendered on the screen, enabling viewing and editing of profile data regardless of current values_
    - _Preservation: One-time prompts still appear for null values; waist form, date picker, notes, submit button, tips widget all unchanged; prompt dismissal behavior unchanged_
    - _Requirements: 1.1, 1.2, 1.3, 2.1, 2.2, 2.3, 2.4, 2.5, 3.1, 3.2, 3.3, 3.4, 3.5_

  - [x] 3.2 Verify bug condition exploration test now passes
    - **Property 1: Expected Behavior** - Collapsible Section Always Visible
    - **IMPORTANT**: Re-run the SAME test from task 1 - do NOT write a new test
    - The test from task 1 encodes the expected behavior (ExpansionTile with "Height & Gender" is always rendered)
    - When this test passes, it confirms the expected behavior is satisfied
    - Run bug condition exploration test from step 1
    - **EXPECTED OUTCOME**: Test PASSES (confirms bug is fixed — collapsible edit section is now present for all profile states)
    - _Requirements: 2.1, 2.2, 2.3_

  - [x] 3.3 Verify preservation tests still pass
    - **Property 2: Preservation** - One-Time Prompts and Form Behavior Unchanged
    - **IMPORTANT**: Re-run the SAME tests from task 2 - do NOT write new tests
    - Run preservation property tests from step 2
    - **EXPECTED OUTCOME**: Tests PASS (confirms no regressions — one-time prompts, form submission, snackbars, and prompt dismissal all behave the same)
    - Confirm all tests still pass after fix (no regressions)

- [x] 4. Checkpoint - Ensure all tests pass
  - Run full test suite: `flutter test`
  - Ensure all property tests pass (both bug condition and preservation)
  - Ensure all existing tests pass (no regressions in other screens)
  - Ask the user if questions arise

## Notes

- The fix is scoped to a single file: `lib/screens/track_visceral_fat_screen.dart`
- The `UserProfile` model (`lib/models/user_profile.dart`) is NOT modified — it already has the needed fields and accessors
- The BLoC layer is NOT modified — `SaveUserProfileEvent` already handles profile persistence
- The new collapsible section uses separate state variables from the one-time prompts to avoid interference
- Property-based tests use `glados` (the existing PBT library in this project)
- Widget tests use `bloc_test` / `mockito` for BLoC mocking with controlled state emissions
- Exploration test (task 1) is expected to FAIL on unfixed code — this is correct and confirms the bug
- Preservation tests (task 2) are expected to PASS on unfixed code — this confirms baseline behavior
- The `ExpansionTile` is always rendered regardless of profile state — it serves both "view existing values" and "set values for the first time" (complementing, not replacing, the one-time prompts)

## Task Dependency Graph

```json
{
  "waves": [
    { "id": 0, "tasks": ["1", "2"] },
    { "id": 1, "tasks": ["3.1"] },
    { "id": 2, "tasks": ["3.2", "3.3"] },
    { "id": 3, "tasks": ["4"] }
  ]
}
```
