import * as jwt from 'jsonwebtoken';
import type { SignOptions } from 'jsonwebtoken';
import { TokenPayload } from '@goodgo/types';

/**
 * EN: Options for JWT token verification
 * VI: Tùy chọn cho việc xác minh JWT token
 */
export interface VerifyTokenOptions {
  /** EN: Secret key used to verify the token / VI: Khóa bí mật dùng để xác minh token */
  secret: string;
  /** EN: Whether to ignore token expiration / VI: Có bỏ qua việc hết hạn token không */
  ignoreExpiration?: boolean;
}

/**
 * EN: Verify and decode a JWT token
 * VI: Xác minh và giải mã JWT token
 *
 * @param token - JWT token string to verify / Chuỗi JWT token cần xác minh
 * @param options - Verification options / Tùy chọn xác minh
 * @returns Decoded token payload / Payload đã giải mã
 * @throws Error if token is invalid or expired / Lỗi nếu token không hợp lệ hoặc hết hạn
 */
export const verifyToken = (token: string, options: VerifyTokenOptions): TokenPayload => {
  try {
    // EN: Verify token signature and decode payload
    // VI: Xác minh chữ ký token và giải mã payload
    const decoded = jwt.verify(token, options.secret, {
      ignoreExpiration: options.ignoreExpiration || false,
    }) as TokenPayload;
    return decoded;
  } catch (error) {
    throw new Error('Invalid or expired token / Token không hợp lệ hoặc hết hạn');
  }
};

/**
 * EN: Decode JWT token without verification (for inspection only)
 * VI: Giải mã JWT token mà không xác minh (chỉ để kiểm tra)
 *
 * @param token - JWT token string to decode / Chuỗi JWT token cần giải mã
 * @returns Decoded token payload or null if invalid / Payload đã giải mã hoặc null nếu không hợp lệ
 */
export const decodeToken = (token: string): TokenPayload | null => {
  try {
    // EN: Decode token without signature verification
    // VI: Giải mã token mà không xác minh chữ ký
    return jwt.decode(token) as TokenPayload;
  } catch (error) {
    return null;
  }
};

/**
 * EN: Create a new JWT token with payload and expiration
 * VI: Tạo JWT token mới với payload và thời gian hết hạn
 *
 * @param payload - Token payload data (without iat/exp) / Dữ liệu payload token (không có iat/exp)
 * @param secret - Secret key for signing / Khóa bí mật để ký
 * @param expiresIn - Token expiration time (default: 15m) / Thời gian hết hạn token (mặc định: 15m)
 * @returns Signed JWT token string / Chuỗi JWT token đã ký
 */
export const createToken = (
  payload: Omit<TokenPayload, 'iat' | 'exp'>,
  secret: string,
  expiresIn: string = '15m'
): string => {
  // EN: Sign payload with secret and expiration
  // VI: Ký payload với secret và thời gian hết hạn
  return jwt.sign(payload, secret, { expiresIn } as SignOptions);
};

/**
 * EN: Check if JWT token has expired
 * VI: Kiểm tra JWT token đã hết hạn chưa
 *
 * @param token - JWT token string to check / Chuỗi JWT token cần kiểm tra
 * @returns True if token is expired or invalid / True nếu token đã hết hạn hoặc không hợp lệ
 */
export const isTokenExpired = (token: string): boolean => {
  try {
    // EN: Decode token and check expiration timestamp
    // VI: Giải mã token và kiểm tra timestamp hết hạn
    const decoded = decodeToken(token);
    if (!decoded || !decoded.exp) {
      return true;
    }
    // EN: Compare expiration time with current time
    // VI: So sánh thời gian hết hạn với thời gian hiện tại
    return decoded.exp * 1000 < Date.now();
  } catch {
    return true;
  }
};

/**
 * EN: Extract JWT token from Authorization header (Bearer format)
 * VI: Trích xuất JWT token từ header Authorization (định dạng Bearer)
 *
 * @param authHeader - Authorization header value / Giá trị header Authorization
 * @returns JWT token string or null if invalid format / Chuỗi JWT token hoặc null nếu định dạng không hợp lệ
 */
export const extractTokenFromHeader = (authHeader: string | undefined): string | null => {
  // EN: Return null if header is missing
  // VI: Trả về null nếu header bị thiếu
  if (!authHeader) {
    return null;
  }

  // EN: Split header into parts (expected: "Bearer <token>")
  // VI: Chia header thành các phần (mong đợi: "Bearer <token>")
  const parts = authHeader.split(' ');
  if (parts.length !== 2 || parts[0] !== 'Bearer') {
    return null;
  }

  return parts[1];
};

// EN: Default export with all authentication utilities
// VI: Export default với tất cả các utility xác thực
export default {
  verifyToken,
  decodeToken,
  createToken,
  isTokenExpired,
  extractTokenFromHeader,
};
