# GetUserProfileQueryHandler

- File ID: file:4pj82p:getuserprofilequeryhandler-cs
- Path: NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs
- Role: handler
- Layer: application

## Purpose

MediatR query handler that reads user profile data from the application's EF Core DbContext, projects it into UserProfileDto and returns it wrapped in a FluentResults Result.

## Key Details

Single MediatR query handler that performs a single EF Core projection query to build a rich UserProfileDto with multiple fallback paths (tenant parsing, subscription plan, last read book fallback), computes an average quiz score, and materializes role names via a join.

## Symbols

- GetUserProfileQueryHandler: MediatR query handler that reads user profile data from the application's EF Core DbContext, projects it into UserProfileDto and returns it wrapped in a FluentResults Result.
- GetUserProfileQueryHandler(): Constructor that captures the IDbContextFactory dependency.
- Handle(): Loads a single user's profile from the database, maps nested DTOs (plan, last read book, roles, quiz score) and returns Result.Ok(profile) or Result.Fail when not found.

## Dependencies

- No resolved dependencies.

## Calls

- No resolved calls.

## Unresolved References

- dependency-target: NexusReader.Data.Persistence
- dependency-target: NexusReader.Application.DTOs.User
- dependency-target: FluentResults
- dependency-target: MediatR
- call-target: NexusReader.Data.Persistence
- call-target: NexusReader.Data.Persistence
- call-target: NexusReader.Data.Persistence
- interaction-target: .Where(u => u.Id == request.UserId)
- interaction-target: ? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)
- interaction-target: }).FirstOrDefault(),
- interaction-target: .Where(ur => ur.UserId == u.Id)

## Coverage

- Symbols: 3
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 3
- Unresolved references: 11
- Control-flow fragments: 2
- Unresolved jumps: 3
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 3

## Control Flow Fragments

- GetUserProfileQueryHandler: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- Handle: 31 nodes, 32 edges, 3 jumps, 0 unsupported constructs

## Diagrams

### GetUserProfileQueryHandler Neighborhood

```mermaid
flowchart LR
    class_158ohhh_getuserprofilequeryhandler("GetUserProfileQueryHandler")
    file_4pj82p_getuserprofilequeryhandler_cs("GetUserProfileQueryHandler")
    method_16gxcfa_handle[["Handle()"]]
    method_1t48k4l_getuserprofilequeryhandler[["GetUserProfileQueryHandler()"]]
```

### GetUserProfileQueryHandler Execution Overview

```mermaid
flowchart TD
    class_158ohhh_getuserprofilequeryhandler("GetUserProfileQueryHandler")
    method_16gxcfa_handle[["Handle()"]]
    method_1t48k4l_getuserprofilequeryhandler[["GetUserProfileQueryHandler()"]]
    unresolved_unresolved_15t570c_call_target{"Unresolved: AppDbContext.Users (DbSet)"}
    unresolved_unresolved_1mpyomv_interaction_target{"Unresolved: }).FirstOrDefault(),"}
    unresolved_unresolved_1o052g9_interaction_target{"Unresolved: .Where(u => u.Id == request.UserId)"}
    unresolved_unresolved_1s9n6fm_interaction_target{"Unresolved: ? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)"}
    unresolved_unresolved_b2sea4_call_target{"Unresolved: AppDbContext.UserRoles (DbSet)"}
    unresolved_unresolved_jtwisz_interaction_target{"Unresolved: .Where(ur => ur.UserId == u.Id)"}
    unresolved_unresolved_nutxq5_call_target{"Unresolved: AppDbContext.Roles (DbSet)"}
    class_158ohhh_getuserprofilequeryhandler -->|contains| method_16gxcfa_handle
    class_158ohhh_getuserprofilequeryhandler -->|contains| method_1t48k4l_getuserprofilequeryhandler
    class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_1mpyomv_interaction_target
    class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_1o052g9_interaction_target
    class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_1s9n6fm_interaction_target
    class_158ohhh_getuserprofilequeryhandler -->|unresolved interaction| unresolved_unresolved_jtwisz_interaction_target
    method_16gxcfa_handle -->|unresolved call| unresolved_unresolved_15t570c_call_target
    method_16gxcfa_handle -->|unresolved call| unresolved_unresolved_b2sea4_call_target
    method_16gxcfa_handle -->|unresolved call| unresolved_unresolved_nutxq5_call_target
```

### Handle() Control Flow

_Warnings: diagram method_16gxcfa_handle__fragment_diagram exceeds preferred complexity thresholds (31 nodes, 32 edges)._

```mermaid
---
config:
  flowchart:
    defaultRenderer: "elk"
---
flowchart TD
    method_16gxcfa_handle__call_21_AppDbContext_Users_DbSet_[["AppDbContext.Users (DbSet)"]]
    method_16gxcfa_handle__call_53_AppDbContext_UserRoles_DbSet_[["AppDbContext.UserRoles (DbSet)"]]
    method_16gxcfa_handle__call_55_AppDbContext_Roles_DbSet_[["AppDbContext.Roles (DbSet)"]]
    method_16gxcfa_handle__action_20_handle_await_20_0__await[["Waits for async work"]]
    method_16gxcfa_handle__action_20_resource_acquisition_20__linear("Create DbContext")
    method_16gxcfa_handle__action_21_db_read_21__linear("Query Users and project into UserProfileDto")
    method_16gxcfa_handle__action_21_handle_await_21_1__await[["Waits for async work"]]
    method_16gxcfa_handle__action_23_handle_mapping_23_3__linear("Maps data or transforms shape")
    method_16gxcfa_handle__action_23_projection_23__linear("Map primitive fields and nested DTOs")
    method_16gxcfa_handle__action_27_branch_fallback_27__linear("TenantId parse with fallback")
    method_16gxcfa_handle__action_28_branch_fallback_28__linear("Subscription plan projection with fallback")
    method_16gxcfa_handle__action_35_conditional_computation_35__linear("Average quiz score calculation with guard on total questions")
    method_16gxcfa_handle__action_38_collection_selection_38__linear("Select last read book or null")
    method_16gxcfa_handle__action_38_handle_mapping_38_5__linear("Maps data or transforms shape")
    method_16gxcfa_handle__action_53_join_53__linear("Build roles array via join")
    method_16gxcfa_handle__action_60_guard_clause_60__condition{"profile == null"}
    method_16gxcfa_handle__action_60_guard_clause_60__false("continue")
    method_16gxcfa_handle__action_60_guard_clause_60__merge("merge")
    method_16gxcfa_handle__action_60_guard_clause_60__true("Result.Fail(\\"Profile not found.\\")")
    method_16gxcfa_handle__action_60_handle_branch_60_8__condition{"profile == null"}
    method_16gxcfa_handle__action_60_handle_branch_60_8__false("false")
    method_16gxcfa_handle__action_60_handle_branch_60_8__merge("merge")
    method_16gxcfa_handle__action_60_handle_branch_60_8__true("true")
    method_16gxcfa_handle__entry(["Handle entry"])
    method_16gxcfa_handle__action_22_handle_repository_read_22_2__linear[("Reads repository or persistence state")]
    method_16gxcfa_handle__action_36_handle_repository_read_36_4__linear[("Reads repository or persistence state")]
    method_16gxcfa_handle__action_52_handle_repository_read_52_6__linear[("Reads repository or persistence state")]
    method_16gxcfa_handle__action_54_handle_repository_read_54_7__linear[("Reads repository or persistence state")]
    method_16gxcfa_handle__action_62_handle_return_62_9__return(["Returns result"])
    method_16gxcfa_handle__action_65_handle_return_65_10__return(["Returns result"])
    method_16gxcfa_handle__action_65_return_65__return(["Return successful result"])
    method_16gxcfa_handle__action_20_handle_await_20_0__await -->|next| method_16gxcfa_handle__action_20_resource_acquisition_20__linear
    method_16gxcfa_handle__action_20_resource_acquisition_20__linear -->|next| method_16gxcfa_handle__action_21_handle_await_21_1__await
    method_16gxcfa_handle__action_21_db_read_21__linear -->|LINQ: filter u.Id == request.UserId projection into UserProfileDto| method_16gxcfa_handle__call_21_AppDbContext_Users_DbSet_
    method_16gxcfa_handle__action_21_handle_await_21_1__await -->|next| method_16gxcfa_handle__action_21_db_read_21__linear
    method_16gxcfa_handle__action_22_handle_repository_read_22_2__linear -->|next| method_16gxcfa_handle__action_23_handle_mapping_23_3__linear
    method_16gxcfa_handle__action_23_handle_mapping_23_3__linear -->|next| method_16gxcfa_handle__action_23_projection_23__linear
    method_16gxcfa_handle__action_23_projection_23__linear -->|next| method_16gxcfa_handle__action_27_branch_fallback_27__linear
    method_16gxcfa_handle__action_27_branch_fallback_27__linear -->|next| method_16gxcfa_handle__action_28_branch_fallback_28__linear
    method_16gxcfa_handle__action_28_branch_fallback_28__linear -->|next| method_16gxcfa_handle__action_35_conditional_computation_35__linear
    method_16gxcfa_handle__action_35_conditional_computation_35__linear -->|next| method_16gxcfa_handle__action_36_handle_repository_read_36_4__linear
    method_16gxcfa_handle__action_36_handle_repository_read_36_4__linear -->|next| method_16gxcfa_handle__action_38_collection_selection_38__linear
    method_16gxcfa_handle__action_38_collection_selection_38__linear -->|next| method_16gxcfa_handle__action_38_handle_mapping_38_5__linear
    method_16gxcfa_handle__action_38_handle_mapping_38_5__linear -->|next| method_16gxcfa_handle__action_52_handle_repository_read_52_6__linear
    method_16gxcfa_handle__action_52_handle_repository_read_52_6__linear -->|next| method_16gxcfa_handle__action_53_join_53__linear
    method_16gxcfa_handle__action_53_join_53__linear -->|Used to filter roles by ur.UserId == u.Id and join with Roles| method_16gxcfa_handle__call_53_AppDbContext_UserRoles_DbSet_
    method_16gxcfa_handle__action_54_handle_repository_read_54_7__linear -->|Joined with UserRoles to select role names| method_16gxcfa_handle__call_55_AppDbContext_Roles_DbSet_
    method_16gxcfa_handle__action_60_guard_clause_60__condition -->|continue| method_16gxcfa_handle__action_60_guard_clause_60__false
    method_16gxcfa_handle__action_60_guard_clause_60__condition -->|Result.Fail Profile not found.| method_16gxcfa_handle__action_60_guard_clause_60__true
    method_16gxcfa_handle__action_60_guard_clause_60__false -->|next| method_16gxcfa_handle__action_60_guard_clause_60__merge
    method_16gxcfa_handle__action_60_guard_clause_60__merge -->|next| method_16gxcfa_handle__action_60_handle_branch_60_8__condition
    method_16gxcfa_handle__action_60_guard_clause_60__true -->|next| method_16gxcfa_handle__action_60_guard_clause_60__merge
    method_16gxcfa_handle__action_60_handle_branch_60_8__condition -->|false| method_16gxcfa_handle__action_60_handle_branch_60_8__false
    method_16gxcfa_handle__action_60_handle_branch_60_8__condition -->|true| method_16gxcfa_handle__action_60_handle_branch_60_8__true
    method_16gxcfa_handle__action_60_handle_branch_60_8__false -->|next| method_16gxcfa_handle__action_60_handle_branch_60_8__merge
    method_16gxcfa_handle__action_60_handle_branch_60_8__merge -->|return| method_16gxcfa_handle__action_62_handle_return_62_9__return
    method_16gxcfa_handle__action_60_handle_branch_60_8__true -->|next| method_16gxcfa_handle__action_60_handle_branch_60_8__merge
    method_16gxcfa_handle__action_62_handle_return_62_9__return -->|return| method_16gxcfa_handle__action_65_handle_return_65_10__return
    method_16gxcfa_handle__action_65_handle_return_65_10__return -->|return| method_16gxcfa_handle__action_65_return_65__return
    method_16gxcfa_handle__call_21_AppDbContext_Users_DbSet_ -->|next| method_16gxcfa_handle__action_22_handle_repository_read_22_2__linear
    method_16gxcfa_handle__call_53_AppDbContext_UserRoles_DbSet_ -->|next| method_16gxcfa_handle__action_54_handle_repository_read_54_7__linear
    method_16gxcfa_handle__call_55_AppDbContext_Roles_DbSet_ -->|next| method_16gxcfa_handle__action_60_guard_clause_60__condition
    method_16gxcfa_handle__entry -->|next| method_16gxcfa_handle__action_20_handle_await_20_0__await
```

## Diagram Validation

- Status: warn
- Warning: Control-flow extraction left 3 unresolved jumps.
- Warning: control-flow: diagram method_16gxcfa_handle__fragment_diagram exceeds preferred complexity thresholds (31 nodes, 32 edges).
