use Mojo::Base -strict;

use Test::More;
use Test::Mojo;
use utils::TOTP;
use utils::JWT;

# 1. Test utils::TOTP
my $secret = utils::TOTP::generate_secret(16);
ok($secret, 'Generated TOTP secret');
is(length($secret), 16, 'TOTP secret length is 16');
like($secret, qr/^[A-Z2-7]{16}$/, 'TOTP secret uses standard Base32 characters');

# Test TOTP generation and verification
my $code = utils::TOTP::generate_totp($secret);
ok($code, "Generated 6-digit TOTP code: $code");
is(length($code), 6, 'TOTP code has 6 digits');
like($code, qr/^\d{6}$/, 'TOTP code is numeric');

# Verify valid code
my $is_valid = utils::TOTP::verify_totp($secret, $code);
is($is_valid, 1, 'Valid TOTP code verified successfully');

# Verify invalid code
my $is_invalid = utils::TOTP::verify_totp($secret, '000000' eq $code ? '111111' : '000000');
is($is_invalid, 0, 'Invalid TOTP code rejected');

# Test otpauth:// URI generation
my $otpauth = utils::TOTP::generate_otpauth_uri($secret, 'shubham@example.com', 'AnchorPanel');
like($otpauth, qr/^otpauth:\/\/totp\/AnchorPanel:shubham%40example\.com\?secret=$secret/, 'Generated valid otpauth URI');

# 2. Test 2FA Temporary JWT Token
my $dummy_config = {
  jwt_secret => 'anchor_2fa_test_secret_123',
  jwt_issuer => 'AnchorBackend',
};

my $dummy_user = {
  id    => 42,
  email => 'shubham@example.com',
};

my $temp_token = utils::JWT::generate_2fa_temp_token($dummy_config, $dummy_user, 300);
ok($temp_token, 'Generated 2FA temporary login token');

my $claims = utils::JWT::verify_2fa_temp_token($dummy_config, $temp_token);
ok($claims, 'Verified 2FA temporary login token');
is($claims->{user_id}, 42, 'Claims user_id matches');
is($claims->{email}, 'shubham@example.com', 'Claims email matches');
is($claims->{type}, '2fa_pending', 'Claims type is 2fa_pending');

# 3. Test Invalid Token
my $fake_claims = utils::JWT::verify_2fa_temp_token($dummy_config, 'invalid.jwt.token');
is($fake_claims, undef, 'Invalid 2FA token correctly returns undef');

# 4. Mojolicious Application Route Validation Tests
my $t = Test::Mojo->new('AnchorBackend');

# Test 2FA verify-login with empty body
$t->post_ok('/api/auth/2fa/verify-login' => json => {})
  ->status_is(400)
  ->json_is('/status' => 'error')
  ->json_is('/message' => 'Invalid or missing request body data');

# Test 2FA verify-login with missing parameters
$t->post_ok('/api/auth/2fa/verify-login' => json => { foo => 'bar' })
  ->status_is(400)
  ->json_is('/status' => 'error')
  ->json_is('/message' => 'Missing required fields: temp_token, code');

# Test 2FA verify-login with invalid temp_token
$t->post_ok('/api/auth/2fa/verify-login' => json => { temp_token => 'invalid_token', code => '123456' })
  ->status_is(401)
  ->json_is('/status' => 'error')
  ->json_is('/message' => 'Invalid or expired 2FA session. Please log in again.');

# Test 2FA setup without authentication token
$t->post_ok('/api/auth/2fa/setup' => json => {})
  ->status_is(401)
  ->json_is('/status' => 'error')
  ->json_is('/message' => 'Authentication required');

# Test 2FA enable without authentication token
$t->post_ok('/api/auth/2fa/enable' => json => { secret => 'JBSWY3DPEHPK3PXP', code => '123456' })
  ->status_is(401)
  ->json_is('/status' => 'error')
  ->json_is('/message' => 'Authentication required');

# Test 2FA disable without authentication token
$t->post_ok('/api/auth/2fa/disable' => json => { password => 'SecretPass' })
  ->status_is(401)
  ->json_is('/status' => 'error')
  ->json_is('/message' => 'Authentication required');

done_testing();
