<?php

namespace App\Http\Controllers\Api\User\Auth;

use App\Http\Controllers\Controller;
use App\Http\Controllers\User\Auth\LoginController;
use App\Http\Controllers\User\Auth\RegisterController;
use App\Http\Controllers\User\Auth\ForgotPasswordController;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
use App\Models\User;
use App\Models\Notification;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use App\Services\AfricasTalkingService;
use App\Models\Coupon;
use App\Models\CouponUsage;
use Carbon\Carbon;
use App\Constants\Status;
use App\Models\BotActivation;
use Illuminate\Support\Facades\DB;

class AuthApiController extends Controller
{
    protected $loginController;
    protected $registerController;
    protected $forgotPasswordController;

    public function __construct()
    {
        $this->loginController = new LoginController();
        $this->registerController = new RegisterController();
        $this->forgotPasswordController = new ForgotPasswordController();
    }
    
    
    
    public function userBotDeposits(Request $request)
    {
        $email = $request->input('email');
    
        $user = User::where('email', $email)->first();
    
        if (!$user) {
            return response()->json([
                'error' => 'User not found'
            ], 404);
        }
    
        $capital = BotActivation::where('user_id', $user->id)->sum('capital');
        
        // return response()->json($capital);
    
        return response()->json([
            'user' => $user,
            'capital' => $capital
        ]);
    }
    
    
    
    public function loginRent(Request $request): JsonResponse
    {
        
        try {
            // Validate login credentials
            $request->validate([
                'email' => 'required',
                'password' => 'required',
            ], [
                'email.required' => 'Email or Username is required',
            ]);

            // Find user
            $username_or_email = $request->email;
            $password = $request->password;
            $user = User::where('email', $username_or_email)
                ->orWhere('username', $username_or_email)
                ->first();

            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Incorrect username or email'
                ], 422);
            }

            // Verify password
            if (!Hash::check($password, $user->password)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Incorrect password'
                ], 422);
            }


            // Create API token
            $token = $user->createToken('API Token')->accessToken;
            
            
            // check if pin is set

            if($user->pin){
                $user->verify_pin = false;
                $user->save();
            }else{
                $user->verify_pin = true;
                $user->save();
            }

            $response = [
                'verify_otp'   => true,
                'user'         => $user,
                'trading_capital' => $user->botActivations->sum('capital'),
                'access_token' => $token,
                'verify_pin' => (bool) $user->verify_pin,
            ];

            // Log notification
            $notification = new Notification();
            $notification->user_id = $user->id;
            $notification->title = "Sign In";
            $notification->message = "Sign in successful at: " . now();
            $notification->status = 0;
            $notification->save();

            return response()->json($response, Response::HTTP_OK);

        } catch (\Exception $e) {
            Log::error('Login failed', [
                'error' => $e->getMessage(),
                'ip' => $ip
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Login failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }


    // add a function to disable users who have failed to ⁠Refer at least two(2) paid users (users who pay the $20 to sign up). or Make a minimum deposit of $50. All within a 20 day window after the sign up.
    public function disableIneligibleUsers()
    {
        $cutoffDate = Carbon::now()->subDays(20);

        $usersToDisable = User::where('status', Status::USER_ACTIVE)
            ->where('created_at', '<=', $cutoffDate)
            ->whereNotNull('coupon')
            ->where(function ($query) {
                // Check if user has less than 2 referrals dealing with payments
                $query->whereHas('referrals', function ($q) {
                    $q->whereHas('payments', function ($p) {
                        $p->where('amount', '>=', 20);
                    });
                }, '<', 2)
                // AND check if user has made no significant deposits
                ->whereDoesntHave('deposits', function ($q) {
                    $q->where('amount', '>=', 50);
                });
            })
            ->get();

        // return $cutoffDate;

        foreach ($usersToDisable as $user) {
            $user->status = 0;
            $user->email = 'disabled_' . $user->email;
            $user->save();

            \Log::info("User ID: {$user->id} has been disabled due to ineligibility.");
        }

        \Log::info("Total users disabled: " . $usersToDisable->count());
    }

    // Add registration fee coupons
    public function payRegFeeCoupon(Request $request)
{
    if (!auth()->check()) {
        return response()->json([
            'message' => 'Unauthenticated.'
        ], 401);
    }

    $request->validate([
        'coupon' => 'required|string'
    ]);

    $user = auth()->user();
    $coupon = trim($request->coupon);

    // Prevent double-redemption by the same user
    if ($user->fee_paid) {
        return response()->json([
            'message' => 'Registration fee has already been paid.',
            'fee_paid' => true
        ], 400);
    }

    $couponCode = Coupon::where('code', $coupon)
        ->where('is_active', 1)
        ->whereColumn('usage_count', '<', 'max_usage')
        ->where(function ($query) {
            $query->whereNull('expires_at')
                  ->orWhere('expires_at', '>', now());
        })
        ->first();

    if (!$couponCode) {
        return response()->json([
            'message' => 'Invalid coupon provided.',
            'fee_paid' => false
        ], 400);
    }

    // Prevent the same user from redeeming the same coupon twice
    $alreadyUsed = CouponUsage::where('coupon_id', $couponCode->id)
        ->where('user_id', $user->id)
        ->exists();

    if ($alreadyUsed) {
        return response()->json([
            'message' => 'You have already redeemed this coupon.',
            'fee_paid' => false
        ], 400);
    }

    try {
        DB::beginTransaction();

        // Lock the coupon row to avoid race conditions on usage_count / max_usage
        $lockedCoupon = Coupon::where('id', $couponCode->id)->lockForUpdate()->first();

        // Re-validate after acquiring the lock
        if (
            !$lockedCoupon ||
            !$lockedCoupon->is_active ||
            ($lockedCoupon->expires_at && $lockedCoupon->expires_at->isPast()) ||
            ($lockedCoupon->max_usage !== null && $lockedCoupon->usage_count >= $lockedCoupon->max_usage)
        ) {
            DB::rollBack();
            return response()->json([
                'message' => 'Coupon is no longer available.',
                'fee_paid' => false
            ], 400);
        }

        // Mark fee as paid on the user and credit the $50 signup bonus
        $user->coupon = $lockedCoupon->code;
        $user->save();
        creditSignupBonus($user);

        // Record coupon usage
        CouponUsage::create([
            'coupon_id'  => $lockedCoupon->id,
            'user_id'    => $user->id,
            'used_at'    => now(),
            'ip_address' => request()->ip(),
            'user_agent' => request()->userAgent(),
        ]);

        // Increment usage counter safely
        $lockedCoupon->increment('usage_count');

        // Give referral bonus if the user was referred
        if ($user->referred_by) {
            $ref = User::where('username', $user->referred_by)->first();

            if ($ref) {
                $ref->balance += 1.5;
                $ref->save();

                recordNewTransaction(1.5, $ref->id, 'credit', 'Referral Bonus', 'usd');
            }
        }

        DB::commit();
    } catch (\Throwable $e) {
        DB::rollBack();

        \Log::error('payRegFeeCoupon failed', [
            'user_id' => $user->id,
            'coupon'  => $coupon,
            'error'   => $e->getMessage(),
        ]);

        return response()->json([
            'message'  => 'Failed to apply coupon. Please try again.',
            'fee_paid' => false,
            'error'    => $e->getMessage(),
        ], 500);
    }

    return response()->json([
        'message' => 'Registration fee waived successfully.',
        'fee_paid' => true
    ]);
}




    // public function payRegFeeCoupon(Request $request)
    // {
    //     if (!auth()->check()) {
    //         return response()->json([
    //             'message' => 'Unauthenticated.'
    //         ], 401);
    //     }
    
    //     $user = auth()->user();
    
    //     $coupon = $request->coupon;
       
    //     // check if coupon is valid
    //     $feeWaived = false;

    //     $couponCode = Coupon::where('code', $coupon)
    //         ->where('is_active', true)
    //         ->where('usage_count', '<', 'max_usage')
    //         ->where(function ($query) {
    //             $query->whereNull('expires_at')
    //                   ->orWhere('expires_at', '>', now());
    //         })
    //         ->first();

    //     if ($couponCode) {
    //         $feeWaived = true;
    //     }
    
    //     if ($feeWaived) {
    //         $user->fee_paid = true;
    //         $user->coupon = $couponCode->code;
    //         $user->save();

    //         // track coupon usage
    //         $couponCode->usage_count += 1;
    //         $couponCode->save();


    //         return response()->json([
    //             'message' => 'Registration fee waived successfully.',
    //             'fee_paid' => true
    //         ]);
    //     } else {
    //         return response()->json([
    //             'message' => 'Invalid coupons provided.',
    //             'fee_paid' => false
    //         ], 400);
    //     }
    // }
    
    
    // check if pin has been verified
    public function isPinVerified()
    {
        if (!auth()->check()) {
            return response()->json([
                'message' => 'Unauthenticated.'
            ], 401);
        }
    
        $user = auth()->user();
    
        return response()->json([
            'verify_pin' => (bool) $user->verify_pin
        ]);
    }
    
    
    
    // Check if user has paid the registration fee and return true or false
    public function isFeePaid()
    {
        if (!auth()->check()) {
            return response()->json([
                'message' => 'Unauthenticated.'
            ], 401);
        }
    
        $user = auth()->user();
    
        return response()->json([
            'fee_paid' => (bool) $user->fee_paid
        ]);
    }
    
    
    
    public function isReferralLegit(Request $request)
    {
        $exists = User::where('username', $request->referred_by)->exists();
    
        return response()->json($exists);
    }



    
    
    /**
     * Send bulk SMS via Africa's Talking API
     */
    public function sendSms()
    {
        // Ideally, these should be stored in your .env file
        $apiKey = "atsk_34c84345a3b6ebbd12c54d014318d9f737ab2f8751465f93b61c290bbc387f11a423eb19";
        $username = "cbrilliance";
        $senderId = "AFRICASTKNG";
        $phoneNo = "+254701117023";
        

        // Prepare the payload (JSON body)
        $payload = [
            "username" => $username,
            "message" => "This is a sample message.",
            // "senderId" => $senderId,
            "phoneNumbers" => [$phoneNo]
        ];

        // Make the POST request
        $response = Http::withHeaders([
            'Accept' => 'application/json',
            'Content-Type' => 'application/json',
            'apiKey' => $apiKey,
        ])->post('https://api.africastalking.com/version1/messaging/bulk', $payload);

        // Return response to frontend
        if ($response->successful()) {
            return response()->json([
                'success' => true,
                'data' => $response->json(),
            ]);
        }

        return response()->json([
            'success' => false,
            'status' => $response->status(),
            'error' => $response->body(),
        ], $response->status());
    }

    
    
    /**
     * Send an SMS using Africa's Talking service
     */
    public function sendSms1(Request $request, AfricasTalkingService $smsService)
    {
        // Validate input (optional if using static values)
        $data = $request->validate([
            'recipients' => 'nullable|array',
            'message'    => 'nullable|string|max:160',
        ]);

        // Use request data or fallback defaults for testing
        $recipients = $data['recipients'] ?? ['+254799117020', '+254722987654'];
        $message    = $data['message'] ?? "Hello from Laravel and Africa's Talking!";

        // Send the SMS
        $result = $smsService->sendSms($recipients, $message);

        // Return JSON response with correct HTTP status
        return response()->json([
            'success'  => $result['success'],
            'message'  => $result['message'],
            'response' => $result['response'] ?? null,
        ], $result['success'] ? 200 : 500);
    }
    
    /**
     * Verify Cloudflare Turnstile token
     * @param string|null $token
     * @param string $ip
     * @return bool
     */
 /**
     * Verify Cloudflare Turnstile token
     * @param string|null $token
     * @param string $ip
     * @return bool
     */
    protected function verifyTurnstileToken(?string $token, string $ip): bool
    {
        // Skip verification if no token provided
        if (!$token) {
            Log::warning('Turnstile token not provided', ['ip' => $ip]);
            // For development: allow without token
            // For production: return false;
            return app()->environment('local', 'development');
        }

        // ✅ BYPASS VERIFICATION FOR TEST TOKENS IN DEVELOPMENT
        if (str_contains($token, 'DUMMY.TOKEN')) {
            Log::info('Turnstile test token detected - bypassing verification', [
                'ip' => $ip,
                'environment' => app()->environment()
            ]);
            
            // Allow test tokens in local/development environments
            if (app()->environment('local', 'development')) {
                return true;
            }
            
            // Block test tokens in production
            Log::warning('Test token used in production environment', ['ip' => $ip]);
            return false;
        }

        // Check if secret key is configured
        $secretKey = env('CLOUDFLARE_TURNSTILE_SECRET_KEY');
        if (!$secretKey) {
            Log::error('Cloudflare Turnstile secret key not configured');
            // Allow in development, block in production
            return app()->environment('local', 'development');
        }

        // ✅ USE TEST SECRET FOR TEST TOKENS
        $isTestToken = str_starts_with($token, '1x') || str_starts_with($token, '2x') || str_starts_with($token, '3x');
        
        if ($isTestToken) {
            Log::info('Cloudflare test token detected', [
                'token_prefix' => substr($token, 0, 10),
                'ip' => $ip,
                'environment' => app()->environment()
            ]);
            
            // Use test secret key for test tokens
            $secretKey = '1x0000000000000000000000000000000AA';
        }

        try {
            Log::info('Verifying Turnstile token', [
                'has_token' => !!$token,
                'is_test_token' => $isTestToken,
                'ip' => $ip,
                'token_prefix' => substr($token, 0, 10) . '...',
                'using_test_secret' => $isTestToken
            ]);

            $response = Http::asForm()
                ->timeout(10) // Add timeout
                ->post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
                    'secret' => $secretKey,
                    'response' => $token,
                    'remoteip' => $ip
                ]);

            if (!$response->successful()) {
                Log::error('Turnstile API request failed', [
                    'status' => $response->status(),
                    'body' => $response->body(),
                    'ip' => $ip
                ]);
                // Allow in development if API fails
                return app()->environment('local', 'development');
            }

            $result = $response->json();

            Log::info('Turnstile verification result', [
                'success' => $result['success'] ?? false,
                'error_codes' => $result['error-codes'] ?? [],
                'challenge_ts' => $result['challenge_ts'] ?? null,
                'hostname' => $result['hostname'] ?? null,
                'ip' => $ip
            ]);

            return $result['success'] ?? false;
        } catch (\Exception $e) {
            Log::error('Turnstile verification exception', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'ip' => $ip
            ]);
            
            // Graceful degradation in development
            if (app()->environment('local', 'development')) {
                Log::warning('Allowing request due to Turnstile API failure in development');
                return true;
            }
            
            return false;
        }
    }
    
    /**
     * Impersonate user (admin functionality)
     * @param Request $request
     * @return JsonResponse
     */
    public function impersonate(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        try {
            $request->validate([
                'email' => 'required',
            ], [
                'email.required' => 'Email is required',
            ]);

            $username_or_email = $request->email;
            $user = User::where('email', $username_or_email)
                ->orWhere('username', $username_or_email)
                ->first();

            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Incorrect username or email'
                ], 422);
            }

            $token = $user->createToken('API Token')->accessToken;

            $response = [
                'verify_otp'   => true,
                'user'         => $user,
                'access_token' => $token,
            ];
            
            return response()->json($response, Response::HTTP_OK);
            
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Impersonation failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Register new user with Turnstile verification
     * @param Request $request
     * @return JsonResponse
     */
    public function register(Request $request): JsonResponse
    {
        // Get IP address (handle proxies and load balancers)
        $ip = $request->header('CF-Connecting-IP') ??
              $request->header('X-Forwarded-For') ??
              $request->ip();
        $ip = trim(explode(',', $ip)[0]);

        // ✅ Verify Turnstile token FIRST before any other checks
        if (!$this->verifyTurnstileToken($request->turnstile_token, $ip)) {
            Log::warning('Registration blocked: Turnstile verification failed', [
                'ip' => $ip,
                'email' => $request->email,
                'has_token' => !!$request->turnstile_token
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Security verification failed. Please refresh the page and try again. Token: ' . $request->turnstile_token
            ], 422);
        }

        Log::info('Turnstile verification passed for registration', [
            'ip' => $ip,
            'email' => $request->email
        ]);

        // ✅ Rate Limiting: Prevent DDOS from same IP
        $rateLimitKey = 'register:' . $ip;
        $maxAttempts = 50;
        $decayMinutes = 60;
        
        if (RateLimiter::tooManyAttempts($rateLimitKey, $maxAttempts)) {
            $seconds = RateLimiter::availableIn($rateLimitKey);
            $minutes = ceil($seconds / 60);
            
            Log::warning('Registration rate limit exceeded', [
                'ip' => $ip,
                'attempts' => RateLimiter::attempts($rateLimitKey),
                'retry_after_minutes' => $minutes
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => "Too many registration attempts from this IP. Please try again in {$minutes} minutes.",
                'retry_after_seconds' => $seconds
            ], 429);
        }

        // ✅ Additional IP-based blocking for suspicious activity
        $suspiciousKey = 'register:suspicious:' . $ip;
        if (Cache::has($suspiciousKey)) {
            Log::warning('Blocked suspicious IP from registration', ['ip' => $ip]);
            return response()->json([
                'status' => 'error',
                'message' => 'Registration temporarily unavailable. Please contact support.'
            ], 403);
        }

        // ✅ Reject requests not coming from a browser
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            Cache::put($suspiciousKey, true, now()->addHours(24));
            
            Log::warning('Registration blocked: Invalid user agent', [
                'ip' => $ip,
                'user_agent' => $userAgent
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
    
        try {
            RateLimiter::hit($rateLimitKey, $decayMinutes * 60);
            
            // Validate registration data
            $request->validate([
                'name' => 'required|string|max:255',
                'email' => 'required|string|email|max:255|unique:users',
                'username' => 'required|string|max:255|unique:users',
                'password' => 'required|string|min:2|confirmed',
                'phone' => 'nullable|string',
                'country' => 'nullable|string',
                'referred_by' => 'nullable|string',
                'pin' =>  'required|string|max:4',
            ]);

            // Check if referred_by user exists
            $ref = null;
            if ($request->referred_by) {
                $ref = User::where('username', $request->referred_by)->first();
            }

            $amount = site('welcome_bonus');
            
            // Create new user
            $user = new User();
            $user->name = $request->name;
            $user->email = strtolower($request->email);
            $user->username = strtolower($request->username);
            $user->password = Hash::make($request->password);
            $user->phone = $request->phone;
            $user->pin = $request->pin;
            $user->country = $request->country;
            $user->email_verified_at = now();
            $user->referred_by = $ref->username ?? null;
            $user->balance = 1;
            $user->save();

            // Record welcome bonus transaction
            recordNewTransaction(1, $user->id, 'credit', "Welcome Bonus");

            // Send welcome email
            sendWelcomeEmail($user);
            
            $code = sendOtp($user->email);

            Log::info('OTP sent to user', [
                'email' => $user->email,
                'code' => $code
            ]);

            // Store OTP code
            $user->otp_code = $code;
            $user->save();

            // Give referral bonus if applicable
            if ($ref) {
                $user->giveReferralBonus(0);
            }
            
            $notification = new Notification();
            $notification->user_id = $user->id;
            $notification->title = "Sign Up";
            $notification->message = "Registration successful at: " . now();
            $notification->status = 0;
            $notification->save();

            Log::info('User registered successfully', [
                'email' => $user->email,
                'ip' => $ip,
                'user_agent' => $userAgent,
                'turnstile_verified' => true
            ]);

            return response()->json([
                'status' => 'success',
                'message' => 'Registration successful'
            ]);
        } catch (\Illuminate\Validation\ValidationException $e) {
            RateLimiter::clear($rateLimitKey);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Validation failed',
                'errors' => $e->errors()
            ], 422);
        } catch (\Exception $e) {
            Log::error('Registration failed', [
                'ip' => $ip,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Registration failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Verify registration OTP
     * @param Request $request
     * @return JsonResponse
     */
    public function registerVerify(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        try {
            $request->validate([
                'email' => 'required|email',
                'otp' => 'required|numeric',
            ]);

            if (!validateOtp($request->otp, $request->email)) {
                return response()->json([
                    'status' => 'error', 
                    'message' => 'Invalid or expired OTP code'
                ], 422);
            }

            $user = User::where('email', $request->email)->first();
            
            if ($user) {
                $user->email_verified_at = now();
                $user->save();
                
                $token = $user->createToken('API Token')->accessToken;
                
                return response()->json([
                    'status' => 'success',
                    'message' => 'Registration verified successfully'
                ]);
            } else {
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not found. Please register first.'
                ], 404);
            }
            
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Registration verification failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Login user with Turnstile verification
     * @param Request $request
     * @return JsonResponse
     */
    public function login(Request $request): JsonResponse
    {
        // Get IP address
        $ip = $request->header('CF-Connecting-IP') ??
              $request->header('X-Forwarded-For') ??
              $request->ip();
        $ip = trim(explode(',', $ip)[0]);

        // ✅ Verify Turnstile token FIRST before any authentication
        if (!$this->verifyTurnstileToken($request->turnstile_token, $ip)) {
            Log::warning('Login blocked: Turnstile verification failed', [
                'ip' => $ip,
                'email' => $request->email,
                'has_token' => !!$request->turnstile_token
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Security verification failed. Please refresh the page and try again. Token: ' . $request->turnstile_token
            ], 422);
        }

        Log::info('Turnstile verification passed for login', [
            'ip' => $ip,
            'email' => $request->email
        ]);

        // ✅ Reject requests not coming from a browser
        $userAgent = $request->header('User-Agent');
        
        // if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
        //     return response()->json([
        //         'status' => 'error',
        //         'message' => 'Invalid source.'
        //     ], 403);
        // }
        
        try {
            // Validate login credentials
            $request->validate([
                'email' => 'required',
                'password' => 'required',
            ], [
                'email.required' => 'Email or Username is required',
            ]);

            // Find user
            $username_or_email = $request->email;
            $password = $request->password;
            $user = User::where('email', $username_or_email)
                ->orWhere('username', $username_or_email)
                ->first();

            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Incorrect username or email'
                ], 422);
            }

            // Verify password
            if (!Hash::check($password, $user->password)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Incorrect password'
                ], 422);
            }

            // Detect browser
            $browser = 'Unknown';
            $userAgentLower = strtolower($userAgent);
            
            if (str_contains($userAgentLower, 'edg')) {
                $browser = 'Microsoft Edge';
            } elseif (str_contains($userAgentLower, 'opr') || str_contains($userAgentLower, 'opera')) {
                $browser = 'Opera';
            } elseif (str_contains($userAgentLower, 'chrome') && !str_contains($userAgentLower, 'chromium')) {
                $browser = 'Google Chrome';
            } elseif (str_contains($userAgentLower, 'safari') && !str_contains($userAgentLower, 'chrome')) {
                $browser = 'Safari';
            } elseif (str_contains($userAgentLower, 'firefox')) {
                $browser = 'Mozilla Firefox';
            } elseif (str_contains($userAgentLower, 'msie') || str_contains($userAgentLower, 'trident')) {
                $browser = 'Internet Explorer';
            }

            // Get country
            $country = 'Unknown';
            try {
                $response = @file_get_contents("https://ipapi.co/{$ip}/country_name/");
                if ($response !== false) {
                    $country = trim($response);
                }
            } catch (\Exception $e) {
                Log::warning("Failed to fetch country for IP {$ip}: " . $e->getMessage());
            }

            Log::info('Login detected', [
                'email' => $user->email,
                'ip' => $ip,
                'browser' => $browser,
                'country' => $country,
                'turnstile_verified' => true
            ]);

            // Send OTP if 2FA not enabled
            // $code = null;
            // if (!$user->g2fa) {
            //     $code = sendOtp($user->email);
            //     Log::info('OTP sent to user', [
            //         'email' => $user->email,
            //         'code' => $code
            //     ]);
            // }
            
            // $code = sendOtp($user->email);

            // // Store OTP
            // $user->otp_code = $code;
            // $user->save();

            // Create API token
            $token = $user->createToken('API Token')->accessToken;
            
            
            // check if pin is set

            if($user->pin){
                $user->verify_pin = false;
                $user->save();
            }else{
                $user->verify_pin = true;
                $user->save();
            }

            $response = [
                'verify_otp'   => true,
                'user'         => $user,
                'trading_capital' => $user->botActivations->sum('capital'),
                'access_token' => $token,
                'verify_pin' => (bool) $user->verify_pin,
            ];

            // Log notification
            $notification = new Notification();
            $notification->user_id = $user->id;
            $notification->title = "Sign In";
            $notification->message = "Sign in successful at: " . now();
            $notification->status = 0;
            $notification->save();

            return response()->json($response, Response::HTTP_OK);

        } catch (\Exception $e) {
            Log::error('Login failed', [
                'error' => $e->getMessage(),
                'ip' => $ip
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Login failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Send login information (device tracking)
     * @param Request $request
     * @return JsonResponse
     */
    public function loginInfo(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        $request->validate([
            'email' => 'required|email',
            'browser' => 'nullable|string',
            'city' => 'nullable|string',
            'color_depth' => 'nullable|integer',
            'country' => 'nullable|string',
            'country_code' => 'nullable|string',
            'ip_address' => 'nullable|ip',
            'language' => 'nullable|string',
            'login_attempt' => 'nullable|boolean',
            'operating_system' => 'nullable|string',
            'platform' => 'nullable|string',
            'region' => 'nullable|string',
            'screen_resolution' => 'nullable|string',
            'success' => 'nullable|boolean',
            'timestamp' => 'nullable|string',
            'timezone' => 'nullable|string',
            'user_agent' => 'nullable|string',
        ]);
        
        $username_or_email = $request->email;
        
        $user = User::where('email', $username_or_email)
            ->orWhere('username', $username_or_email)
            ->first();
    
        if (!$user) {
            return response()->json([
                'status' => 'error',
                'message' => 'Incorrect username or email'
            ], 422);
        }
        
        $user->ip_address = $request->ip_address;
        $user->save();
        
        $loginData = [
            'browser' => $request->browser,
            'city' => $request->city,
            'color_depth' => $request->color_depth,
            'country' => $request->country,
            'country_code' => $request->country_code,
            'ip_address' => $request->ip_address,
            'language' => $request->language,
            'login_attempt' => $request->login_attempt,
            'operating_system' => $request->operating_system,
            'platform' => $request->platform,
            'region' => $request->region,
            'screen_resolution' => $request->screen_resolution,
            'success' => $request->success,
            'timestamp' => $request->timestamp,
            'timezone' => $request->timezone,
            'user_agent' => $request->user_agent,
        ];
        
        // sendLoginEmail($user, $loginData);
        
        return response()->json([
            'status' => 'success',
            'message' => 'Login successful.',
        ]);
    }

    /**
     * Verify login OTP
     * @param Request $request
     * @return JsonResponse
     */
    public function loginVerify(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        try {
            $request->validate([
                'email' => 'required|email',
                'otp' => 'required|numeric',
            ]);

            $otp = $request->otp;
            $email = $request->email;

            $user = User::where('email', $email)->first();

            if ($user && $user->otp_code != $otp) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Invalid or expired OTP code'
                ], 422);
            }
            
            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not found'
                ], 404);
            }

            $token = $user->createToken('API Token')->accessToken;

            // Clear OTP code after successful login
            $user->otp_code = null;
            $user->save();
            
            $notification = new Notification();
            $notification->user_id =  $user->id;
            $notification->title = "OTP Verification";
            $notification->message = "OTP verified successfully at: " . now();
            $notification->status = 0;
            $notification->save();

            return response()->json([
                'status' => 'success',
                'message' => 'OTP Code Verified. Login successful.',
            ]);
            
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Login verification failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Logout user
     * @param Request $request
     * @return JsonResponse
     */
    public function logout(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        try {
            if ($request->user()) {
                $request->user()->token()->revoke();
            }

            return response()->json([
                'status' => 'success',
                'message' => 'Logout successful'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Logout failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Forgot password - send OTP
     * @param Request $request
     * @return JsonResponse
     */
    public function forgotPassword(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        $request->validate([
            'email' => 'required|email',
        ]);

        $user = User::where('email', $request->email)->first();

        $message = 'There is a recent password reset request on your account. Use the otp code below to confirm the reset';
        
        if ($user){
            session()->put('reset-email', $request->email);
            $code = sendOtp($request->email, $message);

            $user->otp_code = $code;
            $user->save();
        }

        return response()->json(['message' => "Password reset request has been sent to your email"]);
    }

    /**
     * Validate forgot password and reset
     * @param Request $request
     * @return JsonResponse
     */
    public function forgotPasswordValidate(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        $request->validate([
            'email' => 'required|string',
            'otp' => 'required|numeric',
            'password' => 'required|confirmed'
        ]);

        $email = $request->email;
        $otp = $request->otp;
        
        $user = User::where('email', $email)->first();
        
        if (!$user) {
            return response()->json([
                'status' => 'error',
                'message' => 'User with this email not found!'
            ], 422);
        }
        
        if ($user && $user->otp_code != $otp) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid or expired OTP code'
            ], 422);
        }

        $update = User::find($user->id);
        $update->password = Hash::make($request->password);
        $update->save();

        return response()->json(['message' => 'Password Changed successfully']);
    }

    /**
     * Get authenticated user data
     * @param Request $request
     * @return JsonResponse
     */
    public function me(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        // if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
        //     return response()->json([
        //         'status' => 'error',
        //         'message' => 'Invalid source.'
        //     ], 403);
        // }
        
        try {
            $user = $request->user();
            
            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not authenticated'
                ], 401);
            }

            return response()->json([
                'status' => 'success',
                'data' => [
                    'user' => $user
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch user data',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Refresh authentication token
     * @param Request $request
     * @return JsonResponse
     */
    public function refreshToken(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        try {
            $user = $request->user();
            
            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not authenticated'
                ], 401);
            }

            $request->user()->token()->revoke();
            $token = $user->createToken('API Token')->accessToken;

            return response()->json([
                'status' => 'success',
                'message' => 'Token refreshed successfully',
                'data' => [
                    'token' => $token,
                    'token_type' => 'Bearer'
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to refresh token',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Verify 2FA code
     * @param Request $request
     * @return JsonResponse
     */
    public function verify2fa(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid source.'
            ], 403);
        }
        
        try {
            $request->validate([
                'otp' => 'required|numeric'
            ]);

            $user = $request->user();
            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not authenticated'
                ], 401);
            }

            $google2fa = new \PragmaRX\Google2FA\Google2FA();
            $valid = $google2fa->verifyKey($user->g2fa_secret, $request->otp);
            
            if ($valid) {
                return response()->json([
                    'status' => 'success',
                    'message' => '2FA verified successfully'
                ]);
            }

            return response()->json([
                'status' => 'error',
                'message' => 'Incorrect or expired 2FA code'
            ], 422);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to verify 2FA',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Resend OTP code
     * @param Request $request
     * @return JsonResponse
     */
    public function resendOtp(Request $request): JsonResponse
    {
        $userAgent = $request->header('User-Agent');
        
        // if (!$userAgent || preg_match('/(curl|httpclient|python|okhttp|wget|Postman|axios|Go-http)/i', $userAgent)) {
        //     return response()->json([
        //         'status' => 'error',
        //         'message' => 'Invalid source.'
        //     ], 403);
        // }
        
        Log::info('resendOtp called', ['request' => $request->all()]);

        try {
            Log::info('Validating request for resendOtp');
            $request->validate([
                'email' => 'required|email'
            ]);
            Log::info('Request validation passed', ['email' => $request->email]);

            $user = User::where('email', $request->email)->first();
            if (!$user) {
                Log::warning('User not found for resendOtp', ['email' => $request->email]);
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not found'
                ], 404);
            }

            $message = 'OTP code has been resent to your registered email';
            Log::info('Sending OTP', ['email' => $request->email]);
            $code = sendOtp($request->email, $message);
            Log::info('OTP sent successfully', ['email' => $request->email, 'code' => $code]);

            $user->otp_code = $code;
            $user->save();
            Log::info('OTP saved to user record', ['user_id' => $user->id, 'email' => $user->email]);

            Log::info('resendOtp completed successfully', ['email' => $request->email]);
            return response()->json([
                'status' => 'success',
                'message' => $message
            ]);
        } catch (\Illuminate\Validation\ValidationException $e) {
            Log::error('Validation failed in resendOtp', [
                'errors' => $e->errors(),
                'request' => $request->all()
            ]);
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid email address',
                'errors' => $e->errors()
            ], 422);
        } catch (\Throwable $e) {
            Log::error('Exception in resendOtp', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
                'email' => $request->email ?? null
            ]);
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to resend OTP',
                'error' => $e->getMessage()
            ], 500);
        }
    }
    
    
    
/**
 * Admin login endpoint - using Passport authentication like users
 */
public function adminLogin(Request $request): JsonResponse
{
    try {
        // Validate login credentials
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ], [
            'email.required' => 'Email is required',
        ]);

        Log::info('Admin login attempt', ['email' => $request->email]);

        // Get credentials
        $email = $request->email;
        $password = $request->password;
        
        // Check if there's an admin with the email
        $admin = \App\Models\Admin::where('email', $email)->first();

        if (!$admin) {
            Log::warning('Admin not found', ['email' => $email]);
            return response()->json([
                'status' => 'error',
                'message' => 'Incorrect email'
            ], 422);
        }

        Log::info('Admin found', ['admin_id' => $admin->id]);

        // Check if password matches
        if (!Hash::check($password, $admin->password)) {
            Log::warning('Password mismatch for admin', ['admin_id' => $admin->id]);
            return response()->json([
                'status' => 'error',
                'message' => 'Incorrect password'
            ], 422);
        }

        Log::info('Password verified for admin', ['admin_id' => $admin->id]);

        // Store admin ID in session
        session()->put('admin', $admin->id);

        // Create Passport token (same as user authentication)
        $message = 'Admin login successful';
        $token = $admin->createToken('Admin API Token')->accessToken;
        
        Log::info('Passport token generated for admin', ['admin_id' => $admin->id]);

        // Log successful admin login
        Log::info('Admin login successful', [
            'admin_id' => $admin->id,
            'admin_email' => $admin->email,
            'ip' => $request->ip(),
            'user_agent' => $request->userAgent()
        ]);

        $response = [
            'verify_otp'   => false, // Admin login doesn't require OTP
            'user'         => $admin, // Keep same key name as user login for consistency
            'access_token' => $token,
        ];

        Log::info('Sending successful response', ['admin_id' => $admin->id]);

        return response()->json($response, Response::HTTP_OK);

    } catch (\Illuminate\Validation\ValidationException $e) {
        Log::error('Admin login validation error', [
            'errors' => $e->errors(),
            'email' => $request->email ?? null
        ]);
        
        return response()->json([
            'status' => 'error',
            'message' => 'Validation failed',
            'errors' => $e->errors()
        ], 422);
    } catch (\Throwable $e) {
        Log::error('Admin login error', [
            'message' => $e->getMessage(),
            'trace' => $e->getTraceAsString(),
            'email' => $request->email ?? null,
            'file' => $e->getFile(),
            'line' => $e->getLine()
        ]);

        return response()->json([
            'status' => 'error',
            'message' => 'Login failed. Please try again.',
            'error' => config('app.debug') ? $e->getMessage() : 'Internal server error',
            'debug_info' => config('app.debug') ? [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => explode("\n", $e->getTraceAsString())
            ] : null
        ], 500);
    }
}

}