import jwt, { SignOptions } from 'jsonwebtoken';
import { UserEntity } from '@/server/modules/users/user.entity';
import debug from 'debug';

const logger = {
  info: debug('backend:jwt:info'),
  error: debug('backend:jwt:error')
};

const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';

export interface JWTPayload {
  id: number;
  username: string;
  roles?: string[];
  openid?: string;
}

export class JWTUtil {
  /**
   * 生成 JWT token
   * @param user 用户实体
   * @param additionalPayload 额外的 payload 数据
   * @returns JWT token
   */
  static generateToken(user: UserEntity, additionalPayload: Partial<JWTPayload> = {}): string {
    if (!user.id || !user.username) {
      throw new Error('用户ID和用户名不能为空');
    }

    const payload: JWTPayload = {
      id: user.id,
      username: user.username,
      roles: user.roles?.map(role => role.name) || [],
      openid: user.openid || undefined,
      ...additionalPayload
    };

    try {
      return jwt.sign(payload, JWT_SECRET, { expiresIn: JWT_EXPIRES_IN as SignOptions['expiresIn']});
    } catch (error) {
      logger.error('生成JWT token失败:', error);
      throw new Error('生成token失败');
    }
  }

  /**
   * 验证 JWT token
   * @param token JWT token
   * @returns 验证后的 payload
   */
  static verifyToken(token: string): JWTPayload {
    try {
      return jwt.verify(token, JWT_SECRET) as JWTPayload;
    } catch (error) {
      logger.error('验证JWT token失败:', error);
      throw new Error('无效的token');
    }
  }

  /**
   * 解码 JWT token（不验证签名）
   * @param token JWT token
   * @returns 解码后的 payload
   */
  static decodeToken(token: string): JWTPayload | null {
    try {
      return jwt.decode(token) as JWTPayload;
    } catch (error) {
      logger.error('解码JWT token失败:', error);
      return null;
    }
  }

  /**
   * 获取 token 的剩余有效期（秒）
   * @param token JWT token
   * @returns 剩余有效期（秒），如果 token 无效则返回 0
   */
  static getTokenRemainingTime(token: string): number {
    try {
      const decoded = jwt.verify(token, JWT_SECRET) as JWTPayload & { exp: number };
      const currentTime = Math.floor(Date.now() / 1000);
      return Math.max(0, decoded.exp - currentTime);
    } catch (error) {
      return 0;
    }
  }
}