/**
 * JWT utilities — configurable issuer and expiry.
 * Uses jose library for standards-compliant JWT handling.
 */

import { SignJWT, jwtVerify } from 'jose';
import type { JwtUtils, JwtUtilsOptions, TokenPayload } from './types.js';

function getSecret(): Uint8Array {
  const secret = process.env.JWT_SECRET;
  if (!secret) throw new Error('JWT_SECRET must be set');
  return new TextEncoder().encode(secret);
}

/**
 * Create a JWT utility set with the given issuer and expiry configuration.
 *
 * @example
 * ```ts
 * const jwt = createJwtUtils({ issuer: "lysnrai", accessTokenExpiry: "1h" });
 * const token = await jwt.createAccessToken({ sub: "u1", email: "a@b.com", role: "admin" });
 * const payload = await jwt.verifyToken(token);
 * ```
 */
export function createJwtUtils(options: JwtUtilsOptions): JwtUtils {
  const { issuer, accessTokenExpiry = '1h', refreshTokenExpiry = '30d' } = options;

  return {
    async createAccessToken(payload) {
      return new SignJWT({
        ...payload,
        productId: payload.productId || issuer,
        type: 'access',
      })
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime(accessTokenExpiry)
        .setIssuer(issuer)
        .sign(getSecret());
    },

    async createRefreshToken(payload) {
      return new SignJWT({
        sub: payload.sub,
        productId: payload.productId || issuer,
        type: 'refresh',
      })
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime(refreshTokenExpiry)
        .setIssuer(issuer)
        .sign(getSecret());
    },

    async verifyToken(token: string) {
      try {
        const { payload } = await jwtVerify(token, getSecret(), {
          issuer,
        });
        return payload as unknown as TokenPayload;
      } catch {
        return null;
      }
    },
  };
}
