import { describe, it, expect, vi, afterEach } from 'vitest';

// Mock passport-jwt before importing JwtStrategy
vi.mock('passport-jwt', () => {
  return {
    Strategy: class MockStrategy {
      constructor(options: any) {
        (this as any)._options = options;
      }
    },
    ExtractJwt: {
      fromAuthHeaderAsBearerToken: () => vi.fn(),
    },
  };
});

vi.mock('@nestjs/passport', () => {
  return {
    PassportStrategy: (StrategyClass: any) => {
      return class extends StrategyClass {};
    },
  };
});

describe('JwtStrategy', () => {
  afterEach(() => {
    vi.unstubAllEnvs();
    vi.resetModules();
  });

  it('throws if JWT_SECRET is missing', async () => {
    vi.stubEnv('JWT_SECRET', '');
    expect(async () => {
      const { JwtStrategy } = await import('../strategies/jwt.strategy');
      new JwtStrategy();
    }).rejects.toThrow('JWT_SECRET environment variable is required');
  });

  it('creates strategy when JWT_SECRET is set', async () => {
    vi.stubEnv('JWT_SECRET', 'test-secret-key');
    const { JwtStrategy } = await import('../strategies/jwt.strategy');
    const strategy = new JwtStrategy();
    expect(strategy).toBeDefined();
  });

  it('validate returns correct payload shape', async () => {
    vi.stubEnv('JWT_SECRET', 'test-secret-key');
    const { JwtStrategy } = await import('../strategies/jwt.strategy');
    const strategy = new JwtStrategy();

    const payload = { sub: 'user-1', phone: '+84912345678', role: 'BUYER', iat: 12345, exp: 99999 };
    const result = strategy.validate(payload);

    expect(result).toEqual({
      sub: 'user-1',
      phone: '+84912345678',
      role: 'BUYER',
    });
  });

  it('validate strips extra fields from payload', async () => {
    vi.stubEnv('JWT_SECRET', 'test-secret-key');
    const { JwtStrategy } = await import('../strategies/jwt.strategy');
    const strategy = new JwtStrategy();

    const payload = { sub: 'user-2', phone: '+84987654321', role: 'ADMIN', iat: 12345, exp: 99999, extra: 'data' } as any;
    const result = strategy.validate(payload);

    expect(result).toEqual({
      sub: 'user-2',
      phone: '+84987654321',
      role: 'ADMIN',
    });
    expect(result).not.toHaveProperty('extra');
    expect(result).not.toHaveProperty('iat');
  });
});
