package com.cameleer.server.core.security;

import java.time.Instant;
import java.util.List;

/**
 * Service for creating and validating JSON Web Tokens (JWT).
 * <p>
 * Access tokens are short-lived (default 1 hour) and used for API authentication.
 * Refresh tokens are longer-lived (default 7 days) and used to obtain new access tokens.
 * Tokens carry a {@code roles} claim for role-based access control.
 */
public interface JwtService {

    /**
     * Validated JWT payload.
     *
     * @param subject     the {@code sub} claim (agent ID or {@code user:<username>})
     * @param application the {@code group} claim (application name)
     * @param environment the {@code env} claim
     * @param roles       the {@code roles} claim (e.g. {@code ["AGENT"]}, {@code ["ADMIN"]})
     * @param issuedAt    the {@code iat} claim (token issue time)
     */
    record JwtValidationResult(String subject, String application, String environment, List<String> roles, Instant issuedAt) {
        /** Backwards-compatible constructor (issuedAt defaults to null). */
        public JwtValidationResult(String subject, String application, String environment, List<String> roles) {
            this(subject, application, environment, roles, null);
        }
    }

    /**
     * Creates a signed access JWT with the given subject, application, and roles.
     */
    String createAccessToken(String subject, String application, String environment, List<String> roles);

    /**
     * Creates a signed refresh JWT with the given subject, application, and roles.
     */
    String createRefreshToken(String subject, String application, String environment, List<String> roles);

    /**
     * Validates an access token and returns the full validation result.
     *
     * @throws InvalidTokenException if the token is invalid, expired, or not an access token
     */
    JwtValidationResult validateAccessToken(String token);

    /**
     * Validates a refresh token and returns the full validation result.
     *
     * @throws InvalidTokenException if the token is invalid, expired, or not a refresh token
     */
    JwtValidationResult validateRefreshToken(String token);

    // --- Backward-compatible defaults (delegate to role-aware methods) ---

    default String createAccessToken(String subject, String application, List<String> roles) {
        return createAccessToken(subject, application, "default", roles);
    }

    default String createAccessToken(String subject, String application) {
        return createAccessToken(subject, application, "default", List.of());
    }

    default String createRefreshToken(String subject, String application, List<String> roles) {
        return createRefreshToken(subject, application, "default", roles);
    }

    default String createRefreshToken(String subject, String application) {
        return createRefreshToken(subject, application, "default", List.of());
    }

    default String validateAndExtractAgentId(String token) {
        return validateAccessToken(token).subject();
    }
}
