import { test, expect } from '@playwright/test';
import { WORKER_URL, createTestAddress, deleteAddress } from '../../fixtures/test-helpers';
import * as crypto from 'crypto';

/**
 * SHA-256 hash matching frontend hashPassword utility.
 */
function hashPassword(password: string): string {
  return crypto.createHash('sha256').update(password).digest('hex');
}

test.describe('Turnstile Login Endpoints (ENABLE_GLOBAL_TURNSTILE_CHECK disabled)', () => {

  test('settings returns enableGlobalTurnstileCheck as false', async ({ request }) => {
    const res = await request.get(`${WORKER_URL}/open_api/settings`);
    expect(res.ok()).toBe(true);
    const settings = await res.json();
    expect(settings.enableGlobalTurnstileCheck).toBe(false);
  });

  test.describe('/open_api/site_login', () => {
    test('returns 401 when no PASSWORDS configured', async ({ request }) => {
      const res = await request.post(`${WORKER_URL}/open_api/site_login`, {
        data: {
          password: hashPassword('any-pass'),
          cf_token: ''
        }
      });
      expect(res.status()).toBe(401);
    });
  });

  test.describe('/open_api/admin_login', () => {
    test('correct hashed password succeeds', async ({ request }) => {
      const res = await request.post(`${WORKER_URL}/open_api/admin_login`, {
        data: {
          password: hashPassword('e2e-admin-pass'),
          cf_token: ''
        }
      });
      expect(res.ok()).toBe(true);
      const body = await res.json();
      expect(body.success).toBe(true);
    });

    test('wrong password returns 401', async ({ request }) => {
      const res = await request.post(`${WORKER_URL}/open_api/admin_login`, {
        data: {
          password: hashPassword('wrong-admin'),
          cf_token: ''
        }
      });
      expect(res.status()).toBe(401);
    });

    test('empty password returns 401', async ({ request }) => {
      const res = await request.post(`${WORKER_URL}/open_api/admin_login`, {
        data: {
          password: '',
          cf_token: ''
        }
      });
      expect(res.status()).toBe(401);
    });
  });

  test.describe('/open_api/credential_login', () => {
    test('valid JWT credential succeeds', async ({ request }) => {
      const { jwt, address } = await createTestAddress(request, 'cred-login');
      try {
        const res = await request.post(`${WORKER_URL}/open_api/credential_login`, {
          data: {
            credential: jwt,
            cf_token: ''
          }
        });
        expect(res.ok()).toBe(true);
        const body = await res.json();
        expect(body.success).toBe(true);
      } finally {
        await deleteAddress(request, jwt);
      }
    });

    test('invalid JWT returns 401', async ({ request }) => {
      const res = await request.post(`${WORKER_URL}/open_api/credential_login`, {
        data: {
          credential: 'invalid.jwt.token',
          cf_token: ''
        }
      });
      expect(res.status()).toBe(401);
    });

    test('empty credential returns 401', async ({ request }) => {
      const res = await request.post(`${WORKER_URL}/open_api/credential_login`, {
        data: {
          credential: '',
          cf_token: ''
        }
      });
      expect(res.status()).toBe(401);
    });
  });

  test.describe('/api/address_login with cf_token', () => {
    test('address login with empty cf_token works when turnstile disabled', async ({ request }) => {
      const { jwt, address } = await createTestAddress(request, 'addr-cf');
      try {
        // Set a password
        await request.post(`${WORKER_URL}/api/address_change_password`, {
          headers: { Authorization: `Bearer ${jwt}` },
          data: { new_password: 'addr-pass-123' },
        });

        // Login with cf_token field present but empty
        const loginRes = await request.post(`${WORKER_URL}/api/address_login`, {
          data: {
            email: address,
            password: 'addr-pass-123',
            cf_token: ''
          },
        });
        expect(loginRes.ok()).toBe(true);
        const body = await loginRes.json();
        expect(body.jwt).toBeTruthy();
      } finally {
        await deleteAddress(request, jwt);
      }
    });
  });
});
