/**
 * eIDAS Provider Tests
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { EIDASProvider } from './eidas';
import fetch from 'node-fetch';

vi.mock('node-fetch');

describe('EIDASProvider', () => {
  let provider: EIDASProvider;
  const config = {
    providerUrl: 'https://eidas.example.com',
    apiKey: 'test-api-key',
  };

  beforeEach(() => {
    provider = new EIDASProvider(config);
    vi.clearAllMocks();
  });

  describe('requestSignature', () => {
    it('should request signature from eIDAS provider', async () => {
      const document = 'test document';
      const mockResponse = {
        signature: 'test-signature',
        certificate: 'test-certificate',
        timestamp: new Date().toISOString(),
      };

      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => mockResponse,
      });

      const result = await provider.requestSignature(document);

      expect(result.signature).toBe(mockResponse.signature);
      expect(result.certificate).toBe(mockResponse.certificate);
      expect(fetch).toHaveBeenCalledWith(
        `${config.providerUrl}/sign`,
        expect.objectContaining({
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${config.apiKey}`,
          },
          body: JSON.stringify({ document }),
        })
      );
    });

    it('should throw error on failed signature request', async () => {
      const document = 'test document';

      (fetch as any).mockResolvedValueOnce({
        ok: false,
        status: 400,
        text: async () => 'Invalid request',
      });

      await expect(provider.requestSignature(document)).rejects.toThrow(
        'eIDAS signature request failed'
      );
    });
  });

  describe('verifySignature', () => {
    it('should verify signature with eIDAS provider', async () => {
      const signature = {
        signature: 'test-signature',
        certificate: 'test-certificate',
        timestamp: new Date(),
      };

      const mockResponse = {
        valid: true,
        certificateChain: ['cert1', 'cert2'],
        issuer: 'CN=Test Issuer',
        subject: 'CN=Test Subject',
        validityPeriod: {
          notBefore: new Date(Date.now() - 1000 * 60 * 60 * 24 * 365).toISOString(),
          notAfter: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365).toISOString(),
        },
      };

      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => mockResponse,
      });

      const result = await provider.verifySignature(signature);

      expect(result).toBe(true);
      expect(fetch).toHaveBeenCalledWith(
        `${config.providerUrl}/verify`,
        expect.objectContaining({
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${config.apiKey}`,
          },
        })
      );
    });

    it('should return false for invalid signature', async () => {
      const signature = {
        signature: 'invalid-signature',
        certificate: 'test-certificate',
        timestamp: new Date(),
      };

      const mockResponse = {
        valid: false,
      };

      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => mockResponse,
      });

      const result = await provider.verifySignature(signature);

      expect(result).toBe(false);
    });

    it('should return false for expired certificate', async () => {
      const signature = {
        signature: 'test-signature',
        certificate: 'test-certificate',
        timestamp: new Date(),
      };

      const mockResponse = {
        valid: true,
        validityPeriod: {
          notBefore: new Date(Date.now() - 1000 * 60 * 60 * 24 * 365 * 2).toISOString(),
          notAfter: new Date(Date.now() - 1000 * 60 * 60 * 24).toISOString(), // Expired
        },
      };

      (fetch as any).mockResolvedValueOnce({
        ok: true,
        json: async () => mockResponse,
      });

      const result = await provider.verifySignature(signature);

      expect(result).toBe(false);
    });
  });
});

