%% Ticket Timer Flow: Opening a ticket to stopping on leave
%% This sequence shows current behavior with IntervalTrackingService + State Machine + UI setInterval

sequenceDiagram
    autonumber
    participant U as User
    participant TD as TicketDetails (component)
    participant HT as useTicketTimeTracking (hook)
    participant SM as IntervalTrackingStateMachine
    participant IS as IntervalTrackingService (IndexedDB)
    participant UIT as UI Timer (setInterval 1s)
    participant NAV as Router/Unmount

    U->>TD: Open Ticket Details
    TD->>TD: mount; derive holderId; memo IntervalTrackingService
    TD->>HT: init hook (ticketId, userId, options)
    HT->>SM: construct(machine); subscribe(listener)
    HT->>SM: refreshLockState()
    SM->>IS: isLockedByOther(ticketId, holderId)
    IS-->>SM: locked? (true/false)
    SM-->>HT: snapshot(state: idle|locked_by_other)
    HT-->>TD: isTracking false

    rect rgb(250,250,210)
      note right of TD: Component-level auto-start attempt (guarded)
      TD->>HT: startTracking(false)
    end

    alt lock acquired
      SM->>IS: acquireLock(ticketId,userId,holderId,force?)
      IS-->>SM: acquired = true
      SM->>IS: startInterval(ticketId, number, title, userId)
      IS-->>SM: intervalId
      Note over SM,IS: No lock TTL or heartbeat. Simple tracking marker is set.
      SM-->>HT: snapshot(state: active, intervalId)
      HT-->>TD: isTracking true
      TD->>IS: getOpenInterval(ticketId, userId)
      IS-->>TD: open interval (startTime)
      TD->>TD: seed elapsed = now - startTime (sec)
      TD->>UIT: setInterval(1000) start
      loop every 1s (visible)
        UIT->>TD: tick +1s (elapsed++)
      end
    else locked by other
      IS-->>SM: acquired = false
      SM-->>HT: snapshot(state: locked_by_other)
      HT-->>TD: isLockedByOther true
      TD->>TD: show "Replace here" dialog on Start click
    end

    par UI lock indicator polling
      TD->>HT: refreshLockState() every ~5s
      HT->>SM: refreshLockState()
      SM->>IS: isLockedByOther(ticketId, holderId)
      IS-->>SM: locked? (true/false)
      SM-->>HT: snapshot(state)
      HT-->>TD: update isLockedByOther
    and Page visibility
      Note over HT,SM: No visibility handling. Timer is strictly mount/unmount.
    end

    opt User presses Pause/Stop or navigates away
      TD->>HT: stopTracking()
      HT->>SM: stop()
      SM->>IS: endInterval(intervalId)
      SM->>IS: releaseLock(ticketId, holderId)
      SM-->>HT: snapshot(state: idle)
      HT-->>TD: isTracking false
      TD->>UIT: clearInterval()
    end

    opt BeforeUnload (best-effort sync)
      SM->>IS: update interval end + delete lock (IndexedDB direct)
    end

    NAV->>TD: unmount
    TD->>HT: stopTracking() in cleanup

%% Notes on past race conditions / complexity sources
%% - Dual auto-start paths: hook autoStart + component effect -> multiple start attempts
%% - visibility handling removed: tracking tied only to mount/unmount
%% - Heartbeat and lock refresh run concurrently with UI timer, impacting state
%% - Seeding UI elapsed from open interval vs. resetting locally may cause jumps if repeated
%% - IndexedDB operations (locks/intervals) add async timing and error paths
