const request = require('supertest');
const app = require('../src/backend/server');
const db = require('../src/backend/database/db');
const { 
  generateDomainVerificationToken, 
  verifyDomainOwnership 
} = require('../src/backend/utils/domainVerification');

describe('Domain Verification API', () => {
  let authToken;
  const mockUserId = 'test-user-123';

  beforeAll(async () => {
    // Setup: Create mock auth token
    // In production, use actual JWT
    authToken = 'mock-jwt-token';
  });

  afterAll(async () => {
    // Cleanup database connections
    await db.pool.end();
  });

  describe('POST /api/passport/domain/request-verification', () => {
    it('should generate verification token for valid domain', async () => {
      const response = await request(app)
        .post('/api/passport/domain/request-verification')
        .set('Authorization', `Bearer ${authToken}`)
        .send({ domain: 'test.example.com' });

      expect(response.status).toBe(200);
      expect(response.body.success).toBe(true);
      expect(response.body.verification).toHaveProperty('domain');
      expect(response.body.verification).toHaveProperty('recordType', 'TXT');
      expect(response.body.verification).toHaveProperty('recordName', '_aethex-verify');
      expect(response.body.verification.recordValue).toMatch(/^aethex-verification=/);
    });

    it('should reject invalid domain format', async () => {
      const response = await request(app)
        .post('/api/passport/domain/request-verification')
        .set('Authorization', `Bearer ${authToken}`)
        .send({ domain: 'invalid domain!' });

      expect(response.status).toBe(400);
      expect(response.body.success).toBe(false);
    });

    it('should require authentication', async () => {
      const response = await request(app)
        .post('/api/passport/domain/request-verification')
        .send({ domain: 'test.example.com' });

      expect(response.status).toBe(401);
    });
  });

  describe('POST /api/passport/domain/verify', () => {
    it('should verify domain with correct DNS record', async () => {
      // This test requires a real domain with TXT record
      // Skip in CI/CD or use mock
      const response = await request(app)
        .post('/api/passport/domain/verify')
        .set('Authorization', `Bearer ${authToken}`)
        .send({ domain: 'test.example.com' });

      expect(response.status).toBeOneOf([200, 400]);
      expect(response.body).toHaveProperty('verified');
    });

    it('should require wallet address for .aethex domains', async () => {
      const response = await request(app)
        .post('/api/passport/domain/verify')
        .set('Authorization', `Bearer ${authToken}`)
        .send({ domain: 'test.aethex' });

      expect(response.status).toBe(400);
      expect(response.body.error).toMatch(/wallet address/i);
    });
  });

  describe('GET /api/passport/domain/status', () => {
    it('should return verification status', async () => {
      const response = await request(app)
        .get('/api/passport/domain/status')
        .set('Authorization', `Bearer ${authToken}`);

      expect(response.status).toBe(200);
      expect(response.body).toHaveProperty('hasVerifiedDomain');
    });
  });
});

describe('Domain Verification Utils', () => {
  const testUserId = 'test-user-456';
  const testDomain = 'test.example.com';

  describe('generateDomainVerificationToken', () => {
    it('should generate unique tokens for same domain', async () => {
      const token1 = await generateDomainVerificationToken(testUserId, testDomain);
      const token2 = await generateDomainVerificationToken(testUserId, testDomain);

      expect(token1.recordValue).not.toBe(token2.recordValue);
      expect(token1.domain).toBe(testDomain);
      expect(token1.recordType).toBe('TXT');
    });

    it('should generate proper DNS record format', async () => {
      const result = await generateDomainVerificationToken(testUserId, testDomain);

      expect(result.fullRecord).toMatch(
        /^_aethex-verify\.test\.example\.com TXT "aethex-verification=.{64}"$/
      );
    });
  });

  describe('verifyDomainOwnership', () => {
    it('should return error if no verification request exists', async () => {
      const result = await verifyDomainOwnership('nonexistent-user', 'nonexistent.com');

      expect(result.verified).toBe(false);
      expect(result.error).toMatch(/no verification request/i);
    });

    it('should check DNS TXT records', async () => {
      // Generate a verification token first
      await generateDomainVerificationToken(testUserId, testDomain);

      // Attempt verification (will fail unless DNS is actually set up)
      const result = await verifyDomainOwnership(testUserId, testDomain);

      expect(result).toHaveProperty('verified');
      expect(result.verified).toBe(false); // Expected to fail without real DNS
    });
  });
});

// Custom Jest matcher
expect.extend({
  toBeOneOf(received, expected) {
    const pass = expected.includes(received);
    return {
      pass,
      message: () => `expected ${received} to be one of ${expected.join(', ')}`
    };
  }
});
