package com.xyw.console.auth;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Service;

@Service
public class AuthTokenService {
  private static final String COOKIE_NAME = "XYW_SESSION";
  private final String secret;
  private final Duration lifetime;
  private final boolean cookieSecure;

  /** 代码作用（白话）：读取部署密钥和会话时长；关联文件：application.yml。关联逻辑（调用链/数据流）：环境变量 -> 配置 -> JWT 签发/验签。 */
  public AuthTokenService(@Value("${xyw.auth.jwt-secret:}") String secret, @Value("${xyw.auth.session-hours:8}") long sessionHours, @Value("${xyw.auth.cookie-secure:false}") boolean cookieSecure) { this.secret = secret; this.lifetime = Duration.ofHours(sessionHours); this.cookieSecure = cookieSecure; }

  /** 代码作用（白话）：为已登录用户签发仅浏览器自动携带的 HttpOnly Cookie；关联文件：AuthService.java。关联逻辑（调用链/数据流）：登录成功 -> JWT -> Set-Cookie -> 后续过滤器。 */
  public void issue(AuthPrincipal principal, HttpServletResponse response) {
    Instant now = Instant.now();
    String token = Jwts.builder().subject(principal.userId().toString()).claim("username", principal.username()).claim("role", principal.roleCode()).claim("version", principal.authVersion()).issuedAt(Date.from(now)).expiration(Date.from(now.plus(lifetime))).signWith(key()).compact();
    response.addHeader("Set-Cookie", ResponseCookie.from(COOKIE_NAME, token).httpOnly(true).secure(cookieSecure).sameSite("Lax").path("/").maxAge(lifetime).build().toString());
  }

  /** 代码作用（白话）：解析并验签 Cookie 中的短期登录票据；关联文件：AuthTokenFilter.java。关联逻辑（调用链/数据流）：请求 Cookie -> JWT claims -> 数据库二次核验。 */
  public AuthPrincipal parse(String token) {
    Claims claims = Jwts.parser().verifyWith((javax.crypto.SecretKey) key()).build().parseSignedClaims(token).getPayload();
    return new AuthPrincipal(Long.valueOf(claims.getSubject()), claims.get("username", String.class), claims.get("role", String.class), claims.get("version", Integer.class));
  }

  /** 代码作用（白话）：清空浏览器登录 Cookie；关联文件：AuthService.java。关联逻辑（调用链/数据流）：登出 -> 过期 Cookie -> 下次请求无身份。 */
  public void clear(HttpServletResponse response) { response.addHeader("Set-Cookie", ResponseCookie.from(COOKIE_NAME, "").httpOnly(true).secure(cookieSecure).sameSite("Lax").path("/").maxAge(Duration.ZERO).build().toString()); }

  /** 代码作用（白话）：从请求 Cookie 取出登录票据；关联文件：AuthTokenFilter.java。关联逻辑（调用链/数据流）：HTTP 请求 -> Cookie 数组 -> JWT 文本。 */
  public String extract(Cookie[] cookies) { if (cookies != null) for (Cookie cookie : cookies) if (COOKIE_NAME.equals(cookie.getName())) return cookie.getValue(); return null; }

  /** 代码作用（白话）：验证密钥足够安全，避免使用默认或过短密钥签发票据；关联文件：application.yml。关联逻辑（调用链/数据流）：配置 -> HMAC Key -> JWT 签名。 */
  private Key key() { if (secret == null || secret.getBytes(StandardCharsets.UTF_8).length < 32) throw new IllegalStateException("认证签名密钥未配置或长度不足"); return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); }
}
