package com.gameplatform.server.controller.auth;

import com.gameplatform.server.model.dto.auth.LoginRequest;
import com.gameplatform.server.model.dto.auth.LoginResponse;
import com.gameplatform.server.security.JwtService;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.Valid;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    private static final Logger log = LoggerFactory.getLogger(AuthController.class);

    private final com.gameplatform.server.service.auth.AuthService authService;
    private final JwtService jwtService;

    public AuthController(com.gameplatform.server.service.auth.AuthService authService, JwtService jwtService) {
        this.authService = authService;
        this.jwtService = jwtService;
    }

    @PostMapping("/login")
    @ResponseStatus(HttpStatus.OK)
    public Mono<LoginResponse> login(@Valid @RequestBody LoginRequest req) {
        // Avoid logging raw usernames at info level
        log.info("/api/auth/login called");
        return authService.login(req);
    }

    @GetMapping("/me")
    public Mono<Object> me(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorization) {
        String token = authorization != null && authorization.startsWith("Bearer ") ? authorization.substring(7) : authorization;
        return Mono.fromCallable(() -> jwtService.parse(token))
                .doOnError(e -> log.warn("/api/auth/me parse token error: {}", e.toString()))
                .map(this::claimsToMe);
    }

    private Object claimsToMe(Claims c) {
        return new java.util.LinkedHashMap<>() {{
            put("userType", c.get("userType"));
            put("userId", c.get("userId"));
            put("username", c.get("username"));
            if ("admin".equals(c.get("userType"))) put("role", c.get("role"));
            put("exp", c.getExpiration());
        }};
    }
}
