package com.ttstd.signaling.controller;

import com.ttstd.signaling.controller.dto.AuthDtos;
import com.ttstd.signaling.security.AuthException;
import com.ttstd.signaling.security.RateLimiter;
import com.ttstd.signaling.service.DeviceIdentityService;
import com.ttstd.signaling.service.TokenPair;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 被控端设备认证接口。
 *
 * <p>被控端无法使用账号登录，改由「SN + 内置共享密钥 HMAC」激活，
 * 激活后凭 deviceSecret 换取短期访问令牌用于 WebSocket 握手。
 */
@RestController
@RequestMapping("/api/device")
public class DeviceAuthController {

    private final DeviceIdentityService deviceIdentityService;
    private final RateLimiter rateLimiter;

    public DeviceAuthController(DeviceIdentityService deviceIdentityService, RateLimiter rateLimiter) {
        this.deviceIdentityService = deviceIdentityService;
        this.rateLimiter = rateLimiter;
    }

    /**
     * 设备激活：返回 deviceUid 与 deviceSecret（deviceSecret 仅此一次明文返回）。
     */
    @PostMapping("/provision")
    public ResponseEntity<AuthDtos.ProvisionResponse> provision(
            @Valid @RequestBody AuthDtos.ProvisionRequest request,
            HttpServletRequest httpRequest) {
        String ip = AuthController.clientIp(httpRequest);
        if (!rateLimiter.tryAcquire("provision:" + ip, 10, 3600)) {
            throw AuthException.tooManyRequests("激活请求过于频繁，请稍后再试");
        }
        DeviceIdentityService.ProvisionResult result = deviceIdentityService.provision(
                request.sn(), request.model(), request.nonce(), request.timestamp(), request.hmac());

        return ResponseEntity.ok(new AuthDtos.ProvisionResponse(
                result.deviceUid(),
                result.deviceSecret(),
                "deviceSecret 仅返回一次，请立即安全存储（建议 Android Keystore）"));
    }

    /**
     * 以 deviceUid + deviceSecret 换取短期设备访问令牌。
     */
    @PostMapping("/token")
    public ResponseEntity<AuthDtos.TokenResponse> token(
            @Valid @RequestBody AuthDtos.DeviceTokenRequest request,
            HttpServletRequest httpRequest) {
        String ip = AuthController.clientIp(httpRequest);
        if (!rateLimiter.tryAcquire("devtoken:" + ip, 60, 3600)) {
            throw AuthException.tooManyRequests("请求过于频繁，请稍后再试");
        }
        TokenPair pair = deviceIdentityService.issueDeviceToken(
                request.deviceUid(), request.deviceSecret());
        return ResponseEntity.ok(new AuthDtos.TokenResponse(
                pair.accessToken(), null, pair.expiresInSeconds(),
                null, pair.principalId(), pair.displayName()));
    }
}
