content: package com.activecourses.upwork.config.security.jwt;
  
  import com.activecourses.upwork.model.User;
  import io.jsonwebtoken.ExpiredJwtException;
  import io.jsonwebtoken.MalformedJwtException;
  import io.jsonwebtoken.UnsupportedJwtException;
  import jakarta.servlet.http.Cookie;
  import jakarta.servlet.http.HttpServletRequest;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import io.jsonwebtoken.Jwts;
  import io.jsonwebtoken.security.Keys;
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.security.core.userdetails.UserDetails;
  import org.springframework.stereotype.Service;
  import org.springframework.http.ResponseCookie;
  import org.springframework.web.util.WebUtils;
  
  import java.security.Key;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Map;
  
  @Service
  public class JwtService {
      private static final Logger logger = LoggerFactory.getLogger(JwtService.class);
  
      @Value("${application.security.jwt.secret_key}")
      private String secretKey;
  
      @Value("${application.security.jwt.expiration}")
      private long jwtExpirationTime;
  
      @Value("${application.security.jwt.refresh_token.expiration}")
      private long refreshJwtExpirationTime;
  
      @Value("${application.security.jwt.cookie.jwt_cookie_name}")
      private String jwtCookie;
  
      @Value("${application.security.jwt.cookie.jwt_refresh_cookie_name}")
      private String jwtRefreshCookie;
  
      @Value("${application.security.jwt.cookie.max_age}")
      private int maxAge;
  
      public ResponseCookie generateJwtCookie(User userPrincipal) {
          String jwt = generateAccessToken(userPrincipal);
          return generateCookie(jwtCookie, jwt, "/api");
      }
      public ResponseCookie generateJwtCookie(UserDetails userPrincipal) {
          String jwt = generateAccessToken(userPrincipal);
          return generateCookie(jwtCookie, jwt, "/api");
      }
  
      public ResponseCookie generateRefreshJwtCookie(String refreshToken) {
          return generateCookie(jwtRefreshCookie, refreshToken, "/api/auth/refresh-token");
      }
  
      public String getJwtFromCookies(HttpServletRequest request) {
          return getCookieValueByName(request, jwtCookie);
      }
  
      public String getJwtRefreshFromCookies(HttpServletRequest request) {
          return getCookieValueByName(request, jwtRefreshCookie);
      }
  
      public ResponseCookie getCleanJwtCookie() {
          return ResponseCookie.from(jwtCookie, "").path("/api").maxAge(0).httpOnly(true).build();
      }
  
      public ResponseCookie getCleanJwtRefreshCookie() {
          return ResponseCookie.from(jwtRefreshCookie, "")
                  .path("/api/auth/refresh-token")
                  .maxAge(0)
                  .httpOnly(true)
                  .build();
      }
  
      public String generateAccessToken(UserDetails userDetails) {
          Map<String, Object> claims = new HashMap<>();
          claims.put("roles", userDetails.getAuthorities());
  
          return generateToken(claims, userDetails.getUsername(), jwtExpirationTime);
      }
  
      public String generateRefreshToken(UserDetails userDetails) {
          Map<String, Object> claims = new HashMap<>();
          claims.put("roles", userDetails.getAuthorities());
  
          return generateToken(claims, userDetails.getUsername(), refreshJwtExpirationTime);
      }
  
      public String generateToken(Map<String, Object> claims, String subject, long expirationTime) {
          return Jwts.builder()
                  .setClaims(claims)
                  .setSubject(subject)
                  .setIssuedAt(new Date(System.currentTimeMillis()))
                  .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                  .signWith(getKey())
                  .compact();
      }
  
      private Key getKey() {
          byte[] keyBytes = secretKey.getBytes();
          return Keys.hmacShaKeyFor(keyBytes);
      }
  
      private ResponseCookie generateCookie(String name, String value, String path) {
          return ResponseCookie.from(name, value)
                  .path(path)
                  .maxAge(maxAge)
                  .httpOnly(true)
                  .secure(true) // Enable only if using HTTPS
                  .sameSite("Strict")
                  .build();
      }
  
      private String getCookieValueByName(HttpServletRequest request, String name) {
          Cookie cookie = WebUtils.getCookie(request, name);
          if (cookie != null) {
              return cookie.getValue();
          } else {
              return null;
          }
      }
  
      public boolean validateJwtToken(String authToken) {
          try {
              Jwts.parserBuilder().setSigningKey(getKey()).build().parseClaimsJws(authToken);
              return true;
          } catch (SecurityException | MalformedJwtException e) {
              logger.error("Invalid JWT signature: {}", e.getMessage());
          } catch (ExpiredJwtException e) {
              logger.error("JWT token is expired: {}", e.getMessage());
          } catch (UnsupportedJwtException e) {
              logger.error("JWT token is unsupported: {}", e.getMessage());
          } catch (IllegalArgumentException e) {
              logger.error("JWT claims string is empty: {}", e.getMessage());
          }
  
          return false;
      }
  
      public String getUserNameFromJwtToken(String token) {
          return Jwts.parserBuilder().setSigningKey(getKey()).build()
                  .parseClaimsJws(token).getBody().getSubject();
      }
  }