package cloud.nstart.terravault.ordinis.restapi.web;

import cloud.nstart.terravault.ordinis.auth.ScopeContext;
import cloud.nstart.terravault.ordinis.domain.DataScope;
import cloud.nstart.terravault.ordinis.restapi.error.OrdinisException;
import cloud.nstart.terravault.ordinis.restapi.service.UserDisplayService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.OffsetDateTime;

/**
 * Resolve UUID (JWT sub) → human-readable display info. Frontend UserCell
 * вызывает {@code GET /api/v1/admin/users/{sub}/display} чтобы показывать
 * username вместо short UUID для чужих пользователей в audit / reviews
 * tables.
 *
 * <p>404 {@code user_not_cached} — sub неизвестен (user ни разу не делал
 * authenticated request на этом backend instance). Frontend fallback'нёт
 * на short UUID.
 *
 * <p>Backed by {@link UserDisplayService} — in-memory cache,
 * заполняется через {@link cloud.nstart.terravault.ordinis.restapi.auth.JwtUserCaptureFilter}
 * на каждом authenticated request.
 */
@RestController
@RequestMapping("/api/v1/admin/users")
public class UserDisplayController {

  private final UserDisplayService service;
  private final ScopeContext scopeContext;

  public UserDisplayController(UserDisplayService service, ScopeContext scopeContext) {
    this.service = service;
    this.scopeContext = scopeContext;
  }

  /** INTERNAL+ scope для лookup — admin staff feature, не для anonymous. */
  private void requireInternal() {
    if (!scopeContext.canAccess(DataScope.INTERNAL)) {
      throw OrdinisException.forbidden(
          "user_display_internal_required",
          "User display lookup доступен только с INTERNAL или RESTRICTED scope.");
    }
  }

  @GetMapping("/{sub}/display")
  public UserDisplayResponse get(@PathVariable String sub) {
    requireInternal();
    return service.find(sub)
        .map(UserDisplayResponse::from)
        .orElseThrow(() -> OrdinisException.notFound(
            "user_not_cached",
            "User " + sub + " not cached. User должен сделать хотя бы один " +
                "authenticated request на этом backend'е чтобы попасть в кэш."));
  }

  public record UserDisplayResponse(
      String sub,
      String preferredUsername,
      String name,
      String email,
      OffsetDateTime updatedAt) {

    static UserDisplayResponse from(UserDisplayService.UserDisplayInfo info) {
      return new UserDisplayResponse(
          info.sub(),
          info.preferredUsername(),
          info.name(),
          info.email(),
          info.updatedAt());
    }
  }
}
