<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

class AuthController extends Controller
{
    /**
     * Register a new user and send OTP to their phone.
     */
  
     public function registerWithOtp(Request $request)
     {
         // Validate input
         $validator = Validator::make($request->all(), [
             'name' => 'required|string|max:255',
             'email' => 'required|email|unique:users,email',
             'phone_number' => 'required|string|regex:/^[0-9]{10}$/|unique:users,phone_number',
             'role' => 'nullable|string|in:user,vendor,driver,admin',
             'referral_code' => 'nullable|string' // Validate referral code
         ]);
     
         if ($validator->fails()) {
             return response()->json(['message' => $validator->errors()->first()], 422);
         }
     
         // Default the role to 'user' if not provided
         $role = $request->role ?? 'user';
     
         // Generate OTP
         $otp = rand(1000, 9999);
         $hashedOtp = Hash::make($otp);
         $otpExpiresAt = now()->addMinutes(15);
     
         // Generate the unique ID based on the role
         $uniqueId = $this->generateUniqueId($role);
     
         // Set the referral code to null if not provided, or use the provided referral code
         $referralCode = $request->filled('referral_code') ? $request->referral_code : null;
     
         // Insert the new user into the database
         $userId = DB::table('users')->insertGetId([
             'name' => $request->name,
             'email' => $request->email,
             'phone_number' => $request->phone_number,
             'otp' => $otp,
             'otp_expiration' => $otpExpiresAt,
             'user_id' => $uniqueId,
             'role' => $role,
             'wallet' => 0, // Initialize wallet balance
             'referral_code' => $referralCode, // Store referral code or null
             'created_at' => now(),
             'updated_at' => now(),
         ]);
     
         // If a referral code was provided and exists in the database
         if ($request->filled('referral_code')) {
             // Find the referrer by user_id (referral_code)
             $referrer = User::where('user_id', $request->referral_code)->first();
             
             // Only proceed if the referrer exists
             if ($referrer) {
                 // Add referral points to the referrer
                 DB::table('referral_points')->insert([
                     'referrer_id' => $referrer->id,
                     'referred_id' => $userId,
                     'points' => 100, // Points for the referral
                     'created_at' => now(),
                     'updated_at' => now(),
                 ]);
     
                 // Update the referrer's wallet
                 DB::table('users')->where('id', $referrer->id)->increment('wallet', 100);
             }
         }
     
         // Send OTP to the user
         $this->sendOtp($request->phone_number, $request->name, $otp);
     
         return response()->json(['message' => 'OTP sent successfully!'], 200);
     }
     
    
    
    // Helper function to generate unique ID based on role
    private function generateUniqueId($role)
    {
        // Determine the prefix based on the role
        $prefix = '';
        switch ($role) {
            case 'vendor':
                $prefix = 'CleaneoVendor';
                break;
            case 'driver':
                $prefix = 'CleaneoAgent';
                break;
            case 'admin':
                $prefix = 'CleaneoAdmin';
                break;
            default:
                $prefix = 'Cleaneo';
                break;
        }
    
        // Fetch the latest user with the same role
        $latestUser = DB::table('users')
                        ->where('role', $role)
                        ->orderBy('id', 'desc')
                        ->first();
    
        // Get the latest numeric part of the ID (e.g., Cleaneo00001 -> 1)
        $lastId = 0;
        if ($latestUser) {
            $lastId = (int)substr($latestUser->user_id, strlen($prefix));
        }
    
        // Increment the last numeric part and format it
        $newId = $lastId + 1;
        $formattedId = str_pad($newId, ($role == 'vendor' ? 6 : 5), '0', STR_PAD_LEFT);
    
        // Return the new unique ID
        return $prefix . $formattedId;
    }
    
    
    private function sendOtp($phoneNumber, $name, $otp)
    {
        $smsApiUrl = "https://drycleaneo.com/update/proxy.php";
        $queryParams = [
            'userid' => 'cleaneoapp',
            'password' => 'EghpgNS3',
            'sendMethod' => 'quick',
            'mobile' => $phoneNumber,
            'msg' => "Hello {$name},\nYour OTP for Cleaneo login/signup is: {$otp}. Thank you.",
            'senderid' => 'CLE123',
            'msgType' => 'text',
            'dltEntityId' => '',
            'dltTemplateId' => '1207171510723882445',
            'duplicatecheck' => 'true',
            'output' => 'json',
        ];

        Http::get($smsApiUrl, $queryParams);
    } 

    /**
     * Login user by sending an OTP to their phone.
     */
    // public function loginWithOtp(Request $request)
    // {
    //     // Validate input
    //     $validator = Validator::make($request->all(), [
    //         'phone_number' => 'required|string|regex:/^[0-9]{10}$/',
    //     ]);

    //     if ($validator->fails()) {
    //         return response()->json(['message' => $validator->errors()->first()], 422);
    //     }

    //     $user = DB::table('users')->where('phone_number', $request->phone_number)->first();

    //     if (!$user) {
    //         return response()->json(['message' => 'User not found. Please register first.'], 404);
    //     }

    //     // Generate OTP
    //     $otp = rand(1000, 9999);
    //     $hashedOtp = Hash::make($otp);
    //     $otpExpiresAt = now()->addMinutes(15);

    //     // Update user's OTP and expiration time
    //     DB::table('users')->where('phone_number', $request->phone_number)->update([
    //         'otp' => $hashedOtp,
    //         'otp_expiration' => $otpExpiresAt,
    //         'updated_at' => now(),
    //     ]);

    //     // Send OTP to the user's phone
    //     $this->sendOtp($request->phone_number, $user->name, $otp);

    //     return response()->json(['message' => 'OTP sent successfully!'], 200);
    // }
public function loginWithOtp(Request $request)
{
    // Validate input
    $validator = Validator::make($request->all(), [
        'phone_number' => 'required|string|regex:/^[0-9]{10}$/',
        'role' => 'nullable|string|in:user,admin,vendor,driver',
    ]);

    if ($validator->fails()) {
        return response()->json(['message' => $validator->errors()->first()], 422);
    }

    // Retrieve the user based on phone number
    $user = DB::table('users')->where('phone_number', $request->phone_number)->first();

    if (!$user) {
        return response()->json(['message' => 'User not found. Please register first.'], 404);
    }

    // Get the role from request (default to 'user' if not provided)
    $requestedRole = $request->role ?? 'user';

    // Check if the user's role matches the requested role
    if ($user->role !== $requestedRole) {
        return response()->json(['message' => ' Please register .'], 403);
    }

    // Generate OTP
    $otp = rand(1000, 9999);
    $hashedOtp = Hash::make($otp);
    $otpExpiresAt = now()->addMinutes(15);

    // Update user's OTP and expiration time
    DB::table('users')->where('phone_number', $request->phone_number)->update([
        'otp' => $otp,
        'otp_expiration' => $otpExpiresAt,
        'updated_at' => now(),
    ]);

    // Send OTP to the user's phone
    $this->sendOtp($request->phone_number, $user->name, $otp);

    return response()->json(['message' => 'OTP sent successfully!','otp' => $otp], 200);
}

    /**
     * Verify OTP and return a JWT token.
     */
//     public function verifyOtp(Request $request)
// {
//     // Validate input
//     $request->validate([
//         'phone_number' => 'required|string|regex:/^[0-9]{10}$/',
//         'otp' => 'required|string',
//     ]);

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

//     if (!$user) {
//         return response()->json(['error' => 'User not found'], 404);
//     }

//     if (is_null($user->otp) || is_null($user->otp_expiration) || Carbon::now()->gt($user->otp_expiration)) {
//         return response()->json(['error' => 'OTP has expired'], 401);
//     }

//     if (!Hash::check($request->otp, $user->otp)) {
//         return response()->json(['error' => 'Invalid OTP'], 401);
//     }

//     // Create token payload
//     $payload = [
//         'iss' => config('app.url'), // Issuer
//         'sub' => $user->id,         // Subject (user ID)
//         'iat' => time(),            // Issued at (current time)
//         'exp' => time() + (15 * 24 * 60 * 60), // Expiration time (15 days from now)
//     ];

//     // Get the secret
//     $jwtSecret = config('app.jwt_secret');

//     // Encode the token
//     $token = JWT::encode($payload, $jwtSecret, 'HS256');

//     // Store the token in the personal_access_tokens table
//     DB::table('personal_access_tokens')->insert([
//         'tokenable_type' => User::class, // Store the model type
//         'tokenable_id' => $user->id, // Store the user ID
//         'name' => 'LOGIN', // Set a default name or a custom name
//         'token' => $token,
//         'abilities' => '*',
//         'last_used_at' => Carbon::now(), // Optional: set the last used time
//         'created_at' => now(),
//         'updated_at' => now(),
//     ]);

//     // Check user role and ensure profile completion
//     if ($user->role === 'vendor') {
//         $vendor = DB::table('vendors')->where('user_id', $user->user_id)->first();

//         if (!$vendor) {
//             return response()->json([
//                 'message' => 'Complete your registration profile.',
//                 'token' => $token
//             ], 200);
//         }

//         if ($vendor->approval_status === 'pending') {
//             return response()->json([
//                 'message' => 'Your account is pending approval.',
//                 'status' => 'pending'
//             ], 403);
//         }
//     } elseif ($user->role === 'driver') {
//         $driver = DB::table('drivers')->where('user_id', $user->user_id)->first();

//         if (!$driver) {
//             return response()->json([
//                 'message' => 'Complete your registration profile.',
//                 'token' => $token
//             ], 200);
//         }
//          if ($driver->approval_status === 'pending') {
//             return response()->json([
//                 'message' => 'Your account is pending approval.',
//                 'status' => 'pending'
//             ], 403);
//         }
//     }

//     return response()->json(['token' => $token], 200);
// }
public function verifyOtp(Request $request)
{
    // Validate input
    $request->validate([
        'phone_number' => 'required|string|regex:/^[0-9]{10}$/',
        'otp' => 'required|string',
    ]);

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

    if (!$user) {
        return response()->json(['error' => 'User not found'], 404);
    }

    if (is_null($user->otp) || is_null($user->otp_expiration) || Carbon::now()->gt($user->otp_expiration)) {
        return response()->json(['error' => 'OTP has expired'], 401);
    }

    if ($request->otp !== $user->otp) {
    // if (!Hash::check($request->otp, $user->otp)) {
        return response()->json(['error' => 'Invalid OTP'], 401);
    }

    // Create token payload
    $payload = [
        'iss' => config('app.url'), // Issuer
        'sub' => $user->id,         // Subject (user ID)
        'iat' => time(),            // Issued at (current time)
        'exp' => time() + (15 * 24 * 60 * 60), // Expiration time (15 days from now)
    ];

    // Get the secret
    $jwtSecret = config('app.jwt_secret');

    // Encode the token
    $token = JWT::encode($payload, $jwtSecret, 'HS256');

    // Store the token in the personal_access_tokens table
    DB::table('personal_access_tokens')->insert([
        'tokenable_type' => User::class, // Store the model type
        'tokenable_id' => $user->id, // Store the user ID
        'name' => 'LOGIN', // Set a default name or a custom name
        'token' => $token,
        'abilities' => '*',
        'last_used_at' => Carbon::now(), // Optional: set the last used time
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    // Check user role and ensure profile completion
    if ($user->role === 'vendor') {
        $vendor = DB::table('vendors')->where('user_id', $user->user_id)->first();

        if (!$vendor) {
            return response()->json([
                'message' => 'Complete your registration profile.',
                'token' => $token
            ], 200);
        }
              if ($vendor->approval_status === 'pending') {
            return response()->json([
                'message' => 'Your account is pending approval.',
                'status' => 'pending',
                'token' => $token
            ], 403);
        }
    } elseif ($user->role === 'driver') {
        $driver = DB::table('drivers')->where('user_id', $user->user_id)->first();

        if (!$driver) {
            return response()->json([
                'message' => 'Complete your registration profile.',
                'token' => $token
            ], 200);
        }
                 if ($driver->approval_status === 'pending') {
            return response()->json([
                'message' => 'Your account is pending approval.',
                'status' => 'pending',
                'token' => $token
            ], 403);
        }
    }

    return response()->json(['token' => $token], 200);
} 


    /**
     * Send OTP to the user's phone via SMS.
     */

    /**
     * Logout and revoke all tokens for the user.
     */
    public function logout(Request $request)
    {
        $user = $request->user();
        $user->tokens()->delete();

        return response()->json(['message' => 'Logged out successfully.'], 200);
    }
}
