import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { exec } from 'node:child_process';
import { promisify } from 'node:util';
import http from 'node:http';
import https from 'node:https';
import fs from 'node:fs';
import path from 'node:path';

const execAsync = promisify(exec);

const ROOT_DIR = path.resolve(__dirname, '..');
const BACKEND_PORT = 3443;
const FRONTEND_PORT = 5174;

describe('DTP Web Application Build Tests', () => {
  describe('Backend Build', () => {
    it('should have dist/web-app.js output', () => {
      const distPath = path.join(ROOT_DIR, 'dist', 'web-app.js');
      expect(fs.existsSync(distPath)).toBe(true);
    });
  });

  describe('Frontend Build', () => {
    it('should build frontend without errors', async () => {
      const { stdout, stderr } = await execAsync('cd frontend && pnpm build', {
        cwd: ROOT_DIR,
        timeout: 120000,
      });
      expect(stderr).toBe('');
      expect(stdout).toContain('built in');
    }, 120000);

    it('should have dist/client/index.html output', () => {
      const indexPath = path.join(ROOT_DIR, 'dist', 'client', 'index.html');
      expect(fs.existsSync(indexPath)).toBe(true);
    });

    it('should have dist/client/assets output', () => {
      const assetsDir = path.join(ROOT_DIR, 'dist', 'client', 'assets');
      expect(fs.existsSync(assetsDir)).toBe(true);
      const jsFiles = fs.readdirSync(assetsDir).filter(f => f.endsWith('.js'));
      const cssFiles = fs.readdirSync(assetsDir).filter(f => f.endsWith('.css'));
      expect(jsFiles.length).toBeGreaterThan(0);
      expect(cssFiles.length).toBeGreaterThan(0);
    });
  });

  describe('Configuration Tests', () => {
    it('should have SSL certificates', () => {
      const keyPath = path.join(ROOT_DIR, 'ssl', 'code-dev.g4dge7.com.key');
      const crtPath = path.join(ROOT_DIR, 'ssl', 'code-dev.g4dge7.com.crt');
      expect(fs.existsSync(keyPath)).toBe(true);
      expect(fs.existsSync(crtPath)).toBe(true);
    });

    it('should have valid SSL key file', () => {
      const keyPath = path.join(ROOT_DIR, 'ssl', 'code-dev.g4dge7.com.key');
      const content = fs.readFileSync(keyPath, 'utf-8');
      expect(content).toContain('-----BEGIN PRIVATE KEY-----');
    });

    it('should have valid SSL certificate', () => {
      const crtPath = path.join(ROOT_DIR, 'ssl', 'code-dev.g4dge7.com.crt');
      const content = fs.readFileSync(crtPath, 'utf-8');
      expect(content).toContain('-----BEGIN CERTIFICATE-----');
    });
  });
});

describe('DTP Web Application Runtime Tests', () => {
  let backendRunning = false;
  let frontendRunning = false;

  afterAll(async () => {
    // Clean up if we started processes (in real tests, you'd manage lifecycle differently)
  });

  describe('Backend Server', () => {
    it('should respond on configured port', async () => {
      // This test checks if the backend is reachable
      // Note: In a real test, you'd start the backend process first
      const options = {
        hostname: 'localhost',
        port: BACKEND_PORT,
        method: 'GET',
        path: '/',
      };

      return new Promise((resolve, reject) => {
        const req = http.request(options, (res) => {
          // Expect some response (will be 404 for / but proves server is running)
          expect(res.statusCode).toBeDefined();
          resolve();
        });

        req.on('error', (err) => {
          // If connection refused, backend isn't running (this is expected for manual testing)
          if (err.code === 'ECONNREFUSED') {
            resolve();
          } else {
            reject(err);
          }
        });

        req.end();
      });
    });
  });

  describe('Frontend Proxy Configuration', () => {
    it('should have vite config with correct proxy settings', () => {
      const viteConfigPath = path.join(ROOT_DIR, 'frontend', 'vite.config.ts');
      const content = fs.readFileSync(viteConfigPath, 'utf-8');

      // Verify proxy targets backend port
      expect(content).toContain(`target: 'http://localhost:${BACKEND_PORT}'`);

      // Verify Socket.io proxy with websockets
      expect(content).toContain("'/socket.io'");
      expect(content).toContain('ws: true');

      // Verify auth proxy
      expect(content).toContain("'/auth'");

      // Verify api proxy
      expect(content).toContain("'/api'");
    });

    it('should have vite config with HTTPS', () => {
      const viteConfigPath = path.join(ROOT_DIR, 'frontend', 'vite.config.ts');
      const content = fs.readFileSync(viteConfigPath, 'utf-8');

      expect(content).toContain('https:');
      expect(content).toContain('.key');
      expect(content).toContain('.crt');
    });

    it('should have correct frontend port in config', () => {
      const viteConfigPath = path.join(ROOT_DIR, 'frontend', 'vite.config.ts');
      const content = fs.readFileSync(viteConfigPath, 'utf-8');

      expect(content).toContain(`port: ${FRONTEND_PORT}`);
    });
  });
});

describe('Environment Configuration', () => {
  it('should have environment variables for HTTPS', () => {
    const envPath = path.join(ROOT_DIR, 'src', 'config', 'env.ts');
    const content = fs.readFileSync(envPath, 'utf-8');

    expect(content).toContain('https');
    expect(content).toContain('port: yamlConfig.https?.port');
    expect(content).toContain('keyFile');
    expect(content).toContain('crtFile');
  });

  it('should have frontend port configured', () => {
    const envPath = path.join(ROOT_DIR, 'src', 'config', 'env.ts');
    const content = fs.readFileSync(envPath, 'utf-8');

    expect(content).toContain('frontend');
    expect(content).toContain('port:');
  });
});

describe('Dependencies', () => {
  it('should have all required dependencies in root package.json', () => {
    const pkgPath = path.join(ROOT_DIR, 'package.json');
    const pkgContent = fs.readFileSync(pkgPath, 'utf-8');
    const pkg = JSON.parse(pkgContent);

    // Backend dependencies
    expect(pkg.dependencies).toHaveProperty('socket.io');
    expect(pkg.dependencies).toHaveProperty('express');
    expect(pkg.dependencies).toHaveProperty('express-session');

    // Frontend dependencies
    expect(pkg.dependencies).toHaveProperty('react');
    expect(pkg.dependencies).toHaveProperty('react-dom');

    // Dev dependencies
    expect(pkg.devDependencies).toHaveProperty('vite');
    expect(pkg.devDependencies).toHaveProperty('typescript');
    expect(pkg.devDependencies).toHaveProperty('vitest');
  });
});