' ============================================================
' WALKGUIDE — DESIGN PATTERNS (GoF)
' Flutter × Spring Boot × In-Device AI
' Pattern 4 of 7: REPOSITORY / PROXY (Structural)
' ============================================================

@startuml WalkGuide_04_Repository_Proxy

skinparam monochrome false
skinparam shadowing false
skinparam defaultFontName Arial
skinparam defaultFontSize 12
skinparam roundCorner 10
skinparam ArrowColor #555555
skinparam ArrowThickness 1.2

skinparam class {
    BackgroundColor #FAFAFA
    BorderColor #AAAAAA
    HeaderBackgroundColor #E8E8E8
    FontColor #222222
    StereotypeFontColor #666666
    AttributeFontColor #333333
}

skinparam package {
    BackgroundColor #F5F5F5
    BorderColor #888888
    FontColor #333333
    FontStyle bold
}

skinparam note {
    BackgroundColor #FFFDE7
    BorderColor #F9A825
    FontColor #444444
    FontSize 11
}

' ============================================================
' PATTERN 4 — REPOSITORY / PROXY (Structural)
' ============================================================

package "④  Repository Pattern  [Structural — Proxy]" #FFF3E0 {

    interface "WalkGuideRepository\n<<interface>>" as WalkGuideRepo {
        + startSession() : Either<Failure, void>
        + stopSession() : Either<Failure, void>
        + logObstacle(ObstacleLogRequest) : Either<Failure, void>
        + getObstacleLogs() : Either<Failure, List<ObstacleLog>>
    }

    interface "ActivityLogRepository\n<<interface>>" as ActivityRepo {
        + getLogs(page) : Either<Failure, List<ActivityLog>>
        + savePending(ActivityLog) : Either<Failure, void>
        + syncPending() : Either<Failure, void>
    }

    class "WalkGuideRepositoryImpl\n<<Proxy>>" as WalkGuideRepoImpl {
        - _remoteDataSource : WalkGuideRemoteDataSource
        - _localDataSource : WalkGuideLocalDataSource
        - _connectivity : ConnectivityPlus
        + startSession() : Either<Failure, void>
        + logObstacle(req) : Either<Failure, void>
        - _isOnline() : bool
    }

    class "ActivityLogRepositoryImpl\n<<Proxy>>" as ActivityRepoImpl {
        - _remoteDataSource : ActivityRemoteDataSource
        - _localDataSource : ActivityLocalDataSource
        + getLogs(page) : Either<Failure, List>
        + syncPending() : Either<Failure, void>
    }

    class "WalkGuideRemoteDataSource\n<<Remote>>" as RemoteDSWalk {
        + startSession() : void
        + logObstacle(req) : void
        ' POST /api/v1/user/obstacle
    }

    class "WalkGuideLocalDataSource\n<<SQLite/Drift>>" as LocalDSWalk {
        + cacheObstacle(ObstacleLog) : void
        + getPendingLogs() : List<ObstacleLog>
        ' Drift ORM — offline first
    }

    WalkGuideRepo <|.. WalkGuideRepoImpl : implements
    ActivityRepo <|.. ActivityRepoImpl : implements
    WalkGuideRepoImpl --> RemoteDSWalk : online path
    WalkGuideRepoImpl --> LocalDSWalk : offline path
}

note bottom of WalkGuideRepoImpl
  Proxy memutuskan sumber data:
  if (isOnline) → fetch remote API
  else → baca/tulis SQLite (Drift)
  Domain layer tidak tahu perbedaannya.
  dartz Either<Failure, Data> untuk typed error.
end note

@enduml
