#!/usr/bin/env node
/**
 * System Integration Test
 * Tests frontend → backend → database connectivity
 */

const http = require("http");
const https = require("https");

const tests = [];
const results = {
  passed: 0,
  failed: 0,
  errors: [],
};

// Test configuration
const BACKEND_URL = "http://localhost:8080";
const FRONTEND_URL = "http://localhost:5100";
const EXTERNAL_URL = "https://houseofprayer.ddns.net";

// Utility: Make HTTP request
function makeRequest(url, options = {}) {
  return new Promise((resolve, reject) => {
    const client = url.startsWith("https") ? https : http;
    const req = client.request(url, options, (res) => {
      let data = "";
      res.on("data", (chunk) => (data += chunk));
      res.on("end", () => {
        resolve({
          statusCode: res.statusCode,
          headers: res.headers,
          body: data,
        });
      });
    });
    req.on("error", reject);
    req.on("timeout", () => reject(new Error("Request timeout")));
    req.setTimeout(5000);
    if (options.body) {
      req.write(options.body);
    }
    req.end();
  });
}

// Test: Backend health endpoint
tests.push({
  name: "Backend Health Check",
  async run() {
    const res = await makeRequest(`${BACKEND_URL}/health`);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    const data = JSON.parse(res.body);
    if (data.status !== "ok") {
      throw new Error(`Health check failed: ${data.status}`);
    }
  },
});

// Test: Backend songs API
tests.push({
  name: "Backend Songs API",
  async run() {
    const res = await makeRequest(`${BACKEND_URL}/api/songs`);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    const data = JSON.parse(res.body);
    if (!data.success) {
      throw new Error("API returned success=false");
    }
    if (!Array.isArray(data.songs)) {
      throw new Error("Expected songs array");
    }
    if (data.songs.length === 0) {
      throw new Error("No songs found in database");
    }
    console.log(`  ✓ Found ${data.songs.length} songs`);
  },
});

// Test: Backend profiles API
tests.push({
  name: "Backend Profiles API",
  async run() {
    const res = await makeRequest(`${BACKEND_URL}/api/profiles`);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    const data = JSON.parse(res.body);
    if (!data.success) {
      throw new Error("API returned success=false");
    }
    if (!Array.isArray(data.profiles)) {
      throw new Error("Expected profiles array");
    }
    console.log(`  ✓ Found ${data.profiles.length} profiles`);
  },
});

// Test: Backend lists API
tests.push({
  name: "Backend Lists API",
  async run() {
    const res = await makeRequest(`${BACKEND_URL}/api/lists`);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    const data = JSON.parse(res.body);
    if (!data.success) {
      throw new Error("API returned success=false");
    }
    if (!Array.isArray(data.lists)) {
      throw new Error("Expected lists array");
    }
    console.log(`  ✓ Found ${data.lists.length} worship lists`);
  },
});

// Test: Backend stats API
tests.push({
  name: "Backend Stats API",
  async run() {
    const res = await makeRequest(`${BACKEND_URL}/api/stats`);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    const data = JSON.parse(res.body);
    if (!data.success) {
      throw new Error("API returned success=false");
    }
    if (!data.stats || typeof data.stats.songs !== "number") {
      throw new Error("Invalid stats format");
    }
    console.log(
      `  ✓ Stats: ${data.stats.songs} songs, ${data.stats.profiles} profiles, ${data.stats.lists} lists`,
    );
  },
});

// Test: Frontend serving
tests.push({
  name: "Frontend Server",
  async run() {
    const res = await makeRequest(FRONTEND_URL);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    if (!res.body.includes("<!doctype html>")) {
      throw new Error("Invalid HTML response");
    }
    if (!res.body.includes("Worship Platform")) {
      throw new Error("Missing expected content");
    }
  },
});

// Test: External HTTPS access
tests.push({
  name: "External HTTPS Access",
  async run() {
    const res = await makeRequest(EXTERNAL_URL);
    if (res.statusCode !== 200) {
      throw new Error(`Expected 200, got ${res.statusCode}`);
    }
    if (!res.body.includes("<!doctype html>")) {
      throw new Error("Invalid HTML response");
    }
  },
});

// Test: CORS headers
tests.push({
  name: "CORS Configuration",
  async run() {
    const res = await makeRequest(`${BACKEND_URL}/api/songs`, {
      method: "OPTIONS",
      headers: {
        Origin: "https://houseofprayer.ddns.net",
        "Access-Control-Request-Method": "GET",
      },
    });
    if (!res.headers["access-control-allow-origin"]) {
      throw new Error("Missing CORS headers");
    }
  },
});

// Run all tests
async function runTests() {
  console.log("\n🔍 Running System Integration Tests...\n");
  console.log("=".repeat(60));

  for (const test of tests) {
    try {
      process.stdout.write(`\n${test.name}... `);
      await test.run();
      console.log("✅ PASSED");
      results.passed++;
    } catch (err) {
      console.log("❌ FAILED");
      console.log(`  Error: ${err.message}`);
      results.failed++;
      results.errors.push({ test: test.name, error: err.message });
    }
  }

  // Summary
  console.log("\n" + "=".repeat(60));
  console.log("\n📊 Test Summary:");
  console.log(`  ✅ Passed: ${results.passed}`);
  console.log(`  ❌ Failed: ${results.failed}`);
  console.log(`  📈 Total:  ${tests.length}`);

  if (results.failed > 0) {
    console.log("\n❌ FAILURES:");
    results.errors.forEach(({ test, error }) => {
      console.log(`  • ${test}: ${error}`);
    });
    process.exit(1);
  } else {
    console.log("\n✅ All tests passed!");
    console.log("\n🎉 System is fully operational!");
    process.exit(0);
  }
}

// Run
runTests().catch((err) => {
  console.error("\n💥 Fatal error:", err);
  process.exit(1);
});
