<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\AppData;
use App\Models\Otp;
use App\Models\User;
use App\Models\UserLevel;
use App\Notifications\BonusWonNotification;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use PgSql\Lob;
use PhpParser\Node\Expr\FuncCall;
use Kreait\Firebase\Factory;

class AuthController extends Controller
{

    public function login(Request $request)
    {

        $request->validate([
            'phone' => 'required|regex:/[0-9]{10}/|digits:10',
            'mpin' => 'required|string',
            'fcm' => 'sometimes|string',
        ]);

        $user = User::where('phone', $request->phone)
            ->with('withdrawDetails')
            ->first();
        if ($user === NULL) {
            $message = "User Not Found! Please Create Account First!";
            return response()->failed($message);
        }

        if (!$user || !Hash::check($request->mpin, $user->password)) {
            $message = "Invalid Credentials!";
            return response()->failed($message);
        }
        if ($user->role == "admin" || $user->role == "sub-admin") {
            $message = "You are not user";
            return response()->failed($message);
        }


        //if we check this then user can't login
        // if (!$user->confirmed) {
        //     $message = "Please Verify Your Account!";
        //     return response()->failed($message);
        // }

        if ($user->blocked) {
            $message = "Your Account Has Been Blocked!";
            return response()->failed($message);
        }

        if (isset($request->fcm)) {
            $user->update(array('fcm' => $request->fcm, 'general_noti' => 1, 'startline_noti' => 1, 'desawar_noti' => 1));
        }

        //user update password_show
        $user->password_show = $request->mpin;
        $user->save();


        try {
            // Initialize Firebase
            $serviceAccountFile = public_path('service-account.json');
            $firebase = (new Factory)
                ->withServiceAccount($serviceAccountFile);
            $messaging = $firebase->createMessaging();

            // Subscribe user to all topics
            if (!empty($user->fcm)) {
                $topics = ["general_notifications", "startline_notifications", "desawar_notifications"];
                foreach ($topics as $topic) {
                    $messaging->subscribeToTopic($topic, [$user->fcm]);
                }
            }
        } catch (\Throwable $th) {
            //throw $th;
        }

        $token = $user->createToken('auth-token')->plainTextToken;
        return response()->success("Login Done!", compact('token', 'user'));
    }

    public function create(Request $request)
    {
        Log::info("create request", $request->all());
        if (!env('ALLOW_EDITING')) {
            return response()->failed("Registration is disabled");
        }

        $request->validate([
            'name' => 'required',
            'phone' => 'required|unique:users,phone|regex:/[0-9]{10}/|digits:10',
            'password' => 'required|string',
            'refferal_code' => 'nullable|numeric|sometimes',
            'agentCode' => 'nullable|string|sometimes'
        ]);

        //if password starts with 0, then return error
        if (substr($request->password, 0, 1) == 0) {
            $message = "Password can't start with 0";
            return response()->failed($message);
        }

        $user_check = User::where('phone', $request->phone)->first();
        if ($user_check !== NULL) {
            $message = "User Already Exist!!";
            return response()->failed($message);
        }

        if (!is_null($request->agentCode)) {
            $refferalUser = User::where('own_code', $request->agentCode)->first();
            if (is_null($refferalUser)) {
                $message = "Agent code is Invalid";
                return response()->failed($message);
            }
        } else {
            if (!is_null($request->refferal_code)) {
                $refferalUser = User::where('own_code', $request->refferal_code)->first();
                if (is_null($refferalUser)) {
                    $message = "Refferal code is Invalid";
                    return response()->failed($message);
                }
            }
        }

        $appData = AppData::first();

        $user =  User::create([
            'name' => $request->name,
            'phone' => $request->phone,
            'balance' => $appData->welcome_bonus,
            'password' => Hash::make($request->password),
            'password_show' => $request->password,
            'role' => 'user',
            "user_id" => isset($refferalUser) ? $refferalUser->id : NULL,
            'own_code' => rand(1000000, 9999999)
        ]);

        // User Refferal Label
        if(isset($refferalUser)) {
            $userLevel1 = User::find($user->user_id); // 1st level
            $userLevel2 = $userLevel1 ? User::find($userLevel1->user_id) : null; // 2nd
            $userLevel3 = $userLevel2 ? User::find($userLevel2->user_id) : null; // 3rd
            $userLevel4 = $userLevel3 ? User::find($userLevel3->user_id) : null; // 4th
            $userLevel5 = $userLevel4 ? User::find($userLevel4->user_id) : null; // 5th

            UserLevel::create([
                'user_id'       => $user->id,
                'user_level_1'  => $userLevel1?->id,
                'user_level_2'  => $userLevel2?->id,
                'user_level_3'  => $userLevel3?->id,
                'user_level_4'  => $userLevel4?->id,
                'user_level_5'  => $userLevel5?->id,
            ]);
        }
        
        
        //if OTP_SYSTEM_REMOVE true then update confirmed to 1
        if (env('OTP_SYSTEM_REMOVE', false)) {
            $user->confirmed = 1;
            $user->save();
        }

        //if refferal code is valid then send bonus to refferal user
        $user->refresh();
        if (isset($refferalUser) && env('DIRECT_BONUS_ENABLE', false)) {
            $balance_before = $refferalUser->balance;
            $amount_to_give = env('DIRECT_INVITE_BONUS', 0);
            $refferalUser->balance = $refferalUser->balance + $amount_to_give;
            $refferalUser->save();
            if ($refferalUser->role == 'agent') {
                $refferalUser->agentTransactions()->create([
                    'previous_amount' => $balance_before,
                    'amount' => $amount_to_give,
                    'current_amount' => $refferalUser->balance,
                    "type" => "bonus",
                    "details" => "You won ($amount_to_give) in bonus"
                ]);
            } else {
                $refferalUser->transactions()->create([
                    'previous_amount' => $balance_before,
                    'amount' => $amount_to_give,
                    'current_amount' => $refferalUser->balance,
                    "type" => "bonus",
                    "details" => "You won ($amount_to_give) in bonus"
                ]);
            }

            $user->notify(new BonusWonNotification($amount_to_give, $user->fcm));
        }

        try {
            // Initialize Firebase
            $serviceAccountFile = public_path('service-account.json');
            $firebase = (new Factory)
                ->withServiceAccount($serviceAccountFile);
            $messaging = $firebase->createMessaging();

            // Subscribe user to all topics
            if (!empty($user->fcm)) {
                $topics = ["general_notifications", "startline_notifications", "desawar_notifications"];
                foreach ($topics as $topic) {
                    $messaging->subscribeToTopic($topic, [$user->fcm]);
                }
            }
        } catch (\Throwable $th) {
            //throw $th;
        }

        if (env('OTP_SYSTEM_REMOVE', false)) {
            $token = $user->createToken('auth-token')->plainTextToken;
            return response()->success("Login Done!", compact('token', 'user'));
        }

        return response()->success("Done", compact('user'));
    }

    public function confirm(Request $request)
    {
        $request->validate([
            'otp' => 'required|string',
            'phone' => 'required|numeric'
        ]);
        $otp = $request->otp;
        $phone = $request->phone;
        if (!OtpController::verifyMeraOtp($otp, $phone)) {
            $message = "Otp is Invalid";
            return response()->failed($message);
        }
        $user = User::where('phone', $phone)->first();
        $user->confirmed = 1;
        $user->save();

        $token = $user->createToken('auth-token')->plainTextToken;
        $message = "Account Confirmed Successfully!";
        return response()->success($message, compact('user', 'token'));
    }

    public function forgetPasswordOtp(Request $request)
    {
        $request->validate([
            'phone' => 'required|numeric'
        ]);

        $user = User::where('phone', $request->phone)->first();
        if (blank($user)) {
            $message = "User not found";
            return response()->failed($message);
        }
        $otpController = new OtpController();
        if (env('ALLOW_EDITING'))
            $otp = rand(1000, 9999);
        else $otp = '1234';
        $user->otps()->create([
            'otp' => $otp,
            'created_at' => now(),
        ]);
        $phoneNumber = $user->phone;
        $message = $otp;
        OtpController::sendOtpMeraOtp($otp, $phoneNumber);

        return response()->success($message, compact('otp'));
    }

    public function forgetPasswordVerify(Request $request)
    {
        $request->validate([
            'phone' => 'required|numeric',
            'mpin' => 'required|numeric',
            'otp' => 'required|string'
        ]);

        $user = User::where('phone', $request->phone)->first();
        if (is_null($user)) {
            $message = "User not found";
            return response()->failed($message);
        }


        $otpResponse = OtpController::verifyMeraOtp($request->otp, $request->phone);
        if ($otpResponse == false) {
            $message = "Otp is Invalid";
            return response()->failed($message);
        }

        //if password starts with 0, then return error
        if (substr($request->mpin, 0, 1) == 0) {
            $message = "Password can't start with 0";
            return response()->failed($message);
        }
        $user->password = Hash::make($request->mpin);
        $user->save();
        return response()->success("Password Has Been Updated!", compact('user'));
    }

    public function updateProfile(Request $request)
    {
        $request->validate([
            'name' => 'sometimes|nullable|string',
            'mpin' => 'sometimes|nullable|string',
        ]);

        /** @var User $user  */
        $user = Auth::user();
        if ($request->filled('name')) {
            $user->name = $request->name;
        }

        if ($request->filled('mpin')) {
            $user->password = Hash::make($request->mpin);
            $user->password_show = $request->mpin;
        }

        $user->save();

        return response()->success("Profile Updated Successfully!", compact('user'));
    }


    public function logout(Request $request)
    {
        /** @var User $user  */
        $user =  Auth::user();
        $user->fcm = NULL;
        $user->save();
        $request->user()->currentaccesstoken()->delete();
        $message = "Logout Successfully";
        return response()->success($message, NULL);
    }
}
