import assert from 'assert';
import fs from 'fs';
import path from 'path';
import { env, validateEnvironment } from '@/lib/config/env';
import { hashPassword, verifyPassword, signAdminToken, verifyAdminToken } from '@/lib/auth/adminAuth';

async function runEnvVerification() {
  console.log('\n======================================================');
  console.log('🧪 RUNNING ENVIRONMENT CONFIGURATION & SECURITY SUITE');
  console.log('======================================================\n');

  let passed = 0;
  let total = 0;

  function test(name: string, fn: () => void | Promise<void>) {
    total++;
    try {
      const res = fn();
      if (res instanceof Promise) {
        return res
          .then(() => {
            console.log(`  ✓ ${name}`);
            passed++;
          })
          .catch((err) => {
            console.error(`  ✕ ${name}: ${err.message}`);
          });
      }
      console.log(`  ✓ ${name}`);
      passed++;
    } catch (err: any) {
      console.error(`  ✕ ${name}: ${err.message}`);
    }
  }

  // 1. File Presence & .gitignore Check
  console.log('📦 1. Environment Files & Git Security:');

  test('.env file exists and contains ADMIN_EMAIL and ADMIN_PASSWORD', () => {
    const envPath = path.resolve(process.cwd(), '.env');
    assert.ok(fs.existsSync(envPath), '.env file must exist');
    const content = fs.readFileSync(envPath, 'utf8');
    assert.ok(content.includes('ADMIN_EMAIL='), '.env must define ADMIN_EMAIL');
    assert.ok(content.includes('ADMIN_PASSWORD='), '.env must define ADMIN_PASSWORD');
    assert.ok(content.includes('ADMIN_EMAIL=admin@meta-connector.app'), 'ADMIN_EMAIL matches requested value');
    assert.ok(content.includes('ADMIN_PASSWORD=admin1234'), 'ADMIN_PASSWORD matches requested value');
  });

  test('.gitignore exists and excludes .env and .env.local files', () => {
    const gitignorePath = path.resolve(process.cwd(), '.gitignore');
    assert.ok(fs.existsSync(gitignorePath), '.gitignore file must exist');
    const content = fs.readFileSync(gitignorePath, 'utf8');
    assert.ok(content.includes('.env'), '.gitignore must ignore .env');
    assert.ok(content.includes('.env*.local') || content.includes('.env.local'), '.gitignore must ignore .env.local');
  });

  test('.env.example exists with placeholder values (no raw secrets exposed)', () => {
    const examplePath = path.resolve(process.cwd(), '.env.example');
    assert.ok(fs.existsSync(examplePath), '.env.example file must exist');
    const content = fs.readFileSync(examplePath, 'utf8');
    assert.ok(content.includes('ADMIN_EMAIL='), '.env.example must define ADMIN_EMAIL template');
    assert.ok(content.includes('ADMIN_PASSWORD='), '.env.example must define ADMIN_PASSWORD template');
    // Ensure no real production API keys leaked into example
    assert.ok(!content.includes('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'), '.env.example must not contain live shopify secret');
    assert.ok(!content.includes('f1ba37b22078ce8aa5ae2ce9e4d2cdb9'), '.env.example must not contain live meta secret');
  });

  // 2. Centralized Config & Validation
  console.log('\n📦 2. Environment Validation & Typing:');

  test('validateEnvironment() succeeds with valid current configuration', () => {
    const result = validateEnvironment(false);
    assert.strictEqual(result.valid, true, 'Environment should be valid with all required keys present');
    assert.strictEqual(result.missing.length, 0, 'No required keys should be missing');
  });

  test('validateEnvironment(true) throws descriptive error when critical keys are missing', () => {
    const originalKey = process.env.SHOPIFY_API_KEY;
    const originalPublicKey = process.env.NEXT_PUBLIC_SHOPIFY_API_KEY;
    try {
      delete process.env.SHOPIFY_API_KEY;
      delete process.env.NEXT_PUBLIC_SHOPIFY_API_KEY;
      assert.throws(
        () => validateEnvironment(true),
        /\[Environment Configuration Error\] Missing required production environment variables/,
        'Strict validation should throw descriptive error'
      );
    } finally {
      process.env.SHOPIFY_API_KEY = originalKey;
      process.env.NEXT_PUBLIC_SHOPIFY_API_KEY = originalPublicKey;
    }
  });

  test('Centralized env object properly exposes SaaS Admin settings', () => {
    assert.strictEqual(env.admin.email, 'admin@meta-connector.app');
    assert.strictEqual(env.admin.password, 'admin1234');
    assert.strictEqual(env.admin.role, 'super_admin');
    assert.ok(env.admin.sessionSecret, 'Admin session secret must be defined');
  });

  test('Centralized env object properly exposes Shopify & Meta settings', () => {
    assert.ok(env.shopify.apiKey, 'Shopify API key must be defined');
    assert.ok(env.shopify.apiSecret, 'Shopify API secret must be defined');
    assert.ok(env.database.host, 'DB Host must be defined');
    assert.ok(env.security.encryptionSecret, 'Encryption secret must be defined');
    assert.strictEqual(env.security.encryptionSecret.length, 64, 'Encryption secret must be 64 hex characters (32 bytes)');
  });

  // 3. SaaS Admin Auth Integration
  console.log('\n📦 3. SaaS Admin Authentication Using Configured Environment:');

  test('Admin authentication verifies against configured ADMIN_PASSWORD', () => {
    const { hash, salt } = hashPassword(env.admin.password);
    assert.ok(verifyPassword(env.admin.password, hash, salt), 'Password verification against env.admin.password succeeds');
    assert.strictEqual(verifyPassword('incorrect_pw', hash, salt), false, 'Incorrect password fails');
  });

  test('Admin JWT token signing and verification uses configured ADMIN_SESSION_SECRET', () => {
    const token = signAdminToken({
      id: 'admin_env_test',
      email: env.admin.email,
      name: env.admin.name,
      role: env.admin.role as any,
    });
    assert.ok(token, 'Token generated');
    const result = verifyAdminToken(token);
    assert.strictEqual(result.valid, true, 'Token signature verified');
    assert.strictEqual(result.payload?.email, env.admin.email, 'Payload contains configured admin email');
  });

  console.log('\n======================================================');
  console.log(`🎉 ENVIRONMENT SUITE COMPLETED: ${passed}/${total} PASSED, ${total - passed} FAILED`);
  console.log('======================================================\n');

  if (total - passed > 0) {
    process.exit(1);
  }
}

runEnvVerification().catch((err) => {
  console.error('Environment verification suite failed:', err);
  process.exit(1);
});
