import { describe, it, expect, vi, beforeEach } from 'vitest';
import { JWTService, JWTPayload } from '../../src/jwt.service.js';

describe('JWT服务', () => {
  beforeEach(() => {
    vi.stubEnv('JWT_SECRET', 'test-secret');
    vi.stubEnv('JWT_EXPIRES_IN', '1h');
  });

  describe('生成token', () => {
    it('应该成功生成JWT token', () => {
      const payload: JWTPayload = {
        id: 1,
        username: 'testuser',
        roles: ['admin'],
        openid: 'test-openid'
      };

      const token = JWTService.generateToken(payload);

      expect(token).toBeDefined();
      expect(typeof token).toBe('string');
      expect(token.split('.')).toHaveLength(3); // JWT token 有3部分
    });

    it('应该使用自定义过期时间生成token', () => {
      const payload: JWTPayload = {
        id: 1,
        username: 'testuser'
      };

      const token = JWTService.generateToken(payload, '2h');

      expect(token).toBeDefined();
    });

    it('缺少用户ID时应该抛出错误', () => {
      const payload = {
        username: 'testuser'
      } as JWTPayload;

      expect(() => {
        JWTService.generateToken(payload);
      }).toThrow('用户ID和用户名不能为空');
    });

    it('缺少用户名时应该抛出错误', () => {
      const payload = {
        id: 1
      } as JWTPayload;

      expect(() => {
        JWTService.generateToken(payload);
      }).toThrow('用户ID和用户名不能为空');
    });
  });

  describe('验证token', () => {
    it('应该成功验证有效的token', () => {
      const payload: JWTPayload = {
        id: 1,
        username: 'testuser'
      };

      const token = JWTService.generateToken(payload);
      const decoded = JWTService.verifyToken(token);

      expect(decoded.id).toBe(payload.id);
      expect(decoded.username).toBe(payload.username);
    });

    it('验证无效token时应该抛出错误', () => {
      const invalidToken = 'invalid.token.here';

      expect(() => {
        JWTService.verifyToken(invalidToken);
      }).toThrow('无效的token');
    });
  });

  describe('解码token', () => {
    it('应该成功解码token', () => {
      const payload: JWTPayload = {
        id: 1,
        username: 'testuser'
      };

      const token = JWTService.generateToken(payload);
      const decoded = JWTService.decodeToken(token);

      expect(decoded?.id).toBe(payload.id);
      expect(decoded?.username).toBe(payload.username);
    });

    it('解码无效token时应该返回null', () => {
      const invalidToken = 'invalid.token.here';
      const decoded = JWTService.decodeToken(invalidToken);

      expect(decoded).toBeNull();
    });
  });

  describe('获取token剩余时间', () => {
    it('应该返回有效的剩余时间', () => {
      const payload: JWTPayload = {
        id: 1,
        username: 'testuser'
      };

      const token = JWTService.generateToken(payload, '1h');
      const remainingTime = JWTService.getTokenRemainingTime(token);

      expect(remainingTime).toBeGreaterThan(0);
      expect(remainingTime).toBeLessThanOrEqual(3600); // 1小时 = 3600秒
    });

    it('无效token应该返回0', () => {
      const invalidToken = 'invalid.token.here';
      const remainingTime = JWTService.getTokenRemainingTime(invalidToken);

      expect(remainingTime).toBe(0);
    });
  });
});