/**
 * Tailscale Route Tests
 *
 * Tests Tailscale status, configuration, and connection-checking endpoints.
 * The Tailscale routes are mounted at /api/tailscale/ on the API router:
 *   - GET /api/tailscale/status          — Tailscale status
 *   - POST /api/tailscale/config         — Update Tailscale configuration
 *   - GET /api/tailscale/check-connection — Check if request comes from Tailscale IP
 *   - GET /api/tailscale/devices         — List Tailscale devices
 *   - POST /api/tailscale/protect-service — Toggle Tailscale-only for a service
 *   - POST /api/tailscale/oauth-config   — OAuth credential setup (requires live API)
 *   - GET /api/tailscale/api-devices     — Enriched device list from API
 *   - POST /api/tailscale/sync           — Trigger API sync
 *   - GET /api/tailscale/acl             — Fetch ACL policy
 */

const request = require('supertest');
const fs = require('fs');
const path = require('path');
const os = require('os');

const testServicesFile = path.join(os.tmpdir(), `tailscale-services-${Date.now()}.json`);
const testConfigFile = path.join(os.tmpdir(), `tailscale-config-${Date.now()}.json`);

process.env.SERVICES_FILE = testServicesFile;
process.env.CONFIG_FILE = testConfigFile;
process.env.ENABLE_HEALTH_CHECKER = 'false';
process.env.NODE_ENV = 'test';

fs.writeFileSync(testServicesFile, '[]', 'utf8');
fs.writeFileSync(testConfigFile, '{}', 'utf8');

const app = require('../server');

describe('Tailscale Routes', () => {
  afterAll(() => {
    try { fs.unlinkSync(testServicesFile); } catch (e) { /* ignore */ }
    try { fs.unlinkSync(testConfigFile); } catch (e) { /* ignore */ }
  });

  describe('GET /api/tailscale/status', () => {
    test('should return 200 with status data', async () => {
      const res = await request(app).get('/api/tailscale/status');

      expect(res.statusCode).toBe(200);
      expect(res.body.success).toBe(true);

      // If Tailscale is not installed in test env, expect installed: false
      if (!res.body.installed) {
        expect(res.body.installed).toBe(false);
        expect(res.body.connected).toBe(false);
        expect(res.body.message).toBeDefined();
      } else {
        // If installed, expect richer data
        expect(res.body).toHaveProperty('connected');
        expect(res.body).toHaveProperty('self');
        expect(res.body).toHaveProperty('config');
        expect(res.body).toHaveProperty('devices');
        expect(res.body).toHaveProperty('deviceCount');
      }
    });
  });

  describe('GET /api/tailscale/check-connection', () => {
    test('should return 200 with connection info', async () => {
      const res = await request(app).get('/api/tailscale/check-connection');

      expect(res.statusCode).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body).toHaveProperty('isTailscale');
      expect(typeof res.body.isTailscale).toBe('boolean');
      expect(res.body).toHaveProperty('clientIP');
    });

    test('should detect non-Tailscale IP for localhost requests', async () => {
      const res = await request(app).get('/api/tailscale/check-connection');

      expect(res.statusCode).toBe(200);
      // Supertest connects via loopback, not a 100.x.x.x address
      expect(res.body.isTailscale).toBe(false);
    });
  });

  describe('GET /api/tailscale/devices', () => {
    test('should return 200 with devices array', async () => {
      const res = await request(app).get('/api/tailscale/devices');

      expect(res.statusCode).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body).toHaveProperty('devices');
      expect(Array.isArray(res.body.devices)).toBe(true);
    });
  });

  describe('POST /api/tailscale/oauth-config', () => {
    test('should reject missing required fields', async () => {
      const res = await request(app)
        .post('/api/tailscale/oauth-config')
        .send({});

      expect(res.statusCode).toBe(400);
    });

    test('should reject partial credentials', async () => {
      const res = await request(app)
        .post('/api/tailscale/oauth-config')
        .send({ clientId: 'test-id' });

      expect(res.statusCode).toBe(400);
    });
  });

  describe('GET /api/tailscale/api-devices', () => {
    test('should return 400 when OAuth is not configured', async () => {
      const res = await request(app).get('/api/tailscale/api-devices');

      expect(res.statusCode).toBe(400);
    });
  });

  describe('POST /api/tailscale/sync', () => {
    test('should return 400 when OAuth is not configured', async () => {
      const res = await request(app).post('/api/tailscale/sync');

      expect(res.statusCode).toBe(400);
    });
  });

  describe('POST /api/tailscale/protect-service', () => {
    test('should reject missing subdomain', async () => {
      const res = await request(app)
        .post('/api/tailscale/protect-service')
        .send({});

      expect(res.statusCode).toBe(400);
    });
  });
});
