<?php

namespace App\Http\Controllers\Api;

use Exception;
use App\Models\User;
use App\Models\Company;
use App\Models\UserFcm;
use Illuminate\Http\Request;
use App\Models\EmailTemplate;
use Illuminate\Validation\Rule;
use App\Helpers\NotificationHelper;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Http\Validators\CompanyValidator;
use Illuminate\Support\Facades\Validator;


class AuthController extends Controller
{
    public function login(Request $request){
        $validator = Validator::make($request->all(), [
            'email'    => 'required|email',
            'password' => 'required'
        ])->stopOnFirstFailure(true);

        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

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

        if ($user != null) {
            if($user->is_block == 1){
                return $this->error('Your account is temporary suspended');
            }

            if (Hash::check($request->password, $user->password)) {

                $user->is_active = 1;
                $user->fcm_token = $request->fcm_token;
                $user->save();
                Auth::login($user);

            } else {
                return $this->error("Invalid Credentials");
            }
        } else {
            return $this->error("Invalid Credentials");
        }

        // ================================
        // SAVE FCM TOKEN IN user_fcms TABLE
        // ================================
        if ($request->filled('fcm_token')) {

            $existing = UserFcm::where('user_id', $user->id)
                                ->where('fcm_token', $request->fcm_token)
                                ->first();

            if (!$existing) {
                UserFcm::create([
                    'user_id'   => $user->id,
                    'fcm_token' => $request->fcm_token,
                    'type'      => $request->type ?? null,
                ]);
            }
        }

        $user->api_token =  auth()->user()->createToken('API Token')->plainTextToken;
        $user->save();
        return $this->success($user);
    }

    public function register(Request $request) {

        try {
            //code...
            $check_user = User::where('email', $request->email)->first();
            $validator = Validator::make($request->all(), [
                'first_name'=> 'required|string',
                'last_name' => 'required|string',
                'email'   => [
                            'required',
                            'email',
                            Rule::unique('users')->whereNull('deleted_at'),
                        ],                // 'phone'     => 'required|unique:users',
                'password'  => 'required',
                'company_type'  => 'required',
            ])->stopOnFirstFailure(true);

            if ($validator->fails()){
                return $this->error($validator->errors()->first(), 400, [], $validator->errors()->first());
            }
            if($check_user == null) {

                $digits   = 6;
                $otpToken =  rand(pow(10, $digits-1), pow(10, $digits)-1);

                $user = User::create([
                    "role_id"   => 2,
                    "password"  => Hash::make($request->password),
                    // "phone"     => $request->phone,
                    "email"     => $request->email,
                    "first_name"=> $request->first_name,
                    "last_name" => $request->last_name,
                    "otp"       => $otpToken,
                    "fcm_token" => $request->fcm_token ?? null,
                    "company_type"=> $request->company_type,
                    "status"    => 0,
                    "is_active" => 1,
                    "is_notify" => 1,
                    "has_company" => 0,
                    "profile_image"=> asset('images/avatar_placeholder.png'),
                    "company" => null,
                ]);
                $token           = $user->createToken('API Token')->plainTextToken;
                $user->api_token = $token;
                $user->save();

                // ================================
                // SAVE FCM TOKEN IN user_fcms TABLE
                // ================================
                if ($request->filled('fcm_token')) {

                    $existing = UserFcm::where('user_id', $user->id)
                                        ->where('fcm_token', $request->fcm_token)
                                        ->first();

                    if (!$existing) {
                        UserFcm::create([
                            'user_id'   => $user->id,
                            'fcm_token' => $request->fcm_token,
                            'type'      => $request->type ?? null,
                        ]);
                    }
                }


                try {
                    $extra = "Thank you for choosing Trading FMCG. Use the following OTP to complete your Sign Up procedures.";
                    $emailDesc = EmailTemplate::where('key', 'REGISTER_OTP')->value('description');
                    if($emailDesc != null){
                        $extra = $emailDesc;
                    }
                    $messageBody = $otpToken;
                    $this->sendMessageToClient($messageBody, $user->email, $extra, $request->first_name);
                } catch (\Exception $ex) {
                }

                return $this->success($user);
            } else {
                return $this->error('Email address is already exist', 400);
            }
        } catch (\Exception $e) {
            return $this->error($e->getMessage());
        }

    }

    public function registerCompnay(Request $request){
        $validator = CompanyValidator::validate($request->all());

        if (!$validator['status']){
            return $this->error('Validation Error', 400, [], $validator['errors']->first());
        }

        $logo = null;
        if($request->has('logo') && $request->file('logo') != null){
            $logoPath = $this->uploadFile($request->file('logo'), 'uploads/users/');
            if(isset($logoPath['path'])){
                $logo = $logoPath['path'];
            }
        }
        $companyData = array(
            'user_id' => Auth::id(),
            'name' => $request->name,
            'email' => $request->email ?? Auth::user()->email,
            'address' => $request->address,
            'city' => $request->city,
            'state' => $request->state,
            'post_code' => $request->post_code,
            'country' => $request->country,
            'type' => Auth::user()->company_type,
            'description' => $request->description,
            'logo' => $logo,
            'slug' => $this->createUniqueSlug($request->name, 'App\Models\Company')
        );
        $company = Company::create($companyData);

        $user = User::with('company')->find(Auth::id());
        $user->has_company = 1;
        $user->save();

        try{
            $admin = User::where('role_id', 1)->first();
            if($admin != null){
                NotificationHelper::sendAndStoreNotification(
                    $admin->fcm_token,
                    $admin->id,
                    'New Company Registered',
                    $company->name.' has signed up at our platform',
                    $user->id,
                    'COMPANY',
                    1,
                    $company->id
                );
            }
        }catch(Exception $ex){

        }

        return $this->success($user);
    }

    public function resendOtpToken(Request $request) {
        $validator = Validator::make($request->all(), [
            'api_token' => 'required'
        ])->stopOnFirstFailure(true);
        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

        $user = User::where("api_token", $request->api_token)->first();
        if ($user != null) {
            $digits = 6;
            $otpToken = rand(pow(10, $digits - 1), pow(10, $digits) - 1);
            $user->otp = $otpToken;
            $user->save();

            try {
                $extra = "Thank you for choosing Trading FMCG. Use the following OTP to complete your Sign Up procedures.";
                $emailDesc = EmailTemplate::where('key', 'REGISTER_OTP')->value('description');
                if($emailDesc != null){
                    $extra = $emailDesc;
                }
                $messageBody = $otpToken;
                $this->sendMessageToClient($messageBody, $user->email, $extra, $user->first_name);
                return $this->success(array("otp" => $otpToken));
            } catch (\Exception $ex) {
                return $this->error($ex->getMessage());
            }
        }else{
            return $this->error('Invalid User');
        }
    }

    public function verifyToken(Request $request) {
        $validator = Validator::make($request->all(), [
            'otp_token' => 'required',
            'api_token' => 'required'
        ])->stopOnFirstFailure(true);

        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }
        if ($request->has('otp_token')) {
            $otpToken = $request->otp_token;
            $user = User::with('company')->where("api_token", $request->api_token)->first();
            if (isset($user->otp) && $user->otp == $otpToken) {
                $user->api_token = $user->createToken('API Token')->plainTextToken;
                $user->status    = 1;
                $user->save();
                // Auth::login($user);
                return $this->success($user, 'Token Verified Successfully.');
            } else {
                return $this->error('Invalid OTP Token', 400);
            }
        } else {
            return $this->error('OTP Token Required', 400);
        }
    }

    public function setPassword(Request $request) {
        $validator = Validator::make($request->all(), [
            'api_token'        => 'required',
            'password'         => 'required',
        ])->stopOnFirstFailure(true);

        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

        $user            = User::with('company')->where("api_token", $request->api_token)->first();
        $user->api_token = $user->createToken('API Token')->plainTextToken;
        $user->password  = Hash::make($request->password);
        $user->save();
        Auth::login($user);
        return $this->success($user, 'Password Set Successfully.');
    }

    public function updateFcmToken(Request $request){
        $validator = Validator::make($request->all(), [
            'fcm_token' => 'required'
        ])->stopOnFirstFailure(true);

        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }
        $user = User::with('company')->find(Auth::id());
        $user->fcm_token = $request->fcm_token;
        $user->save();
        return $this->success($user, 'FCM Token Updated Successfully.');
    }

    public function logout(Request $request) {
        $user = User::find(Auth::id());
        $user->is_active = 0;
        $user->save();

        // ================================
        // DELETE FCM TOKEN FROM user_fcms
        // ================================
        if ($request->filled('fcm_token')) {

            $fcm = UserFcm::where('user_id', $user->id)
                        ->where('fcm_token', $request->fcm_token)
                        ->first();

            if ($fcm) {
                $fcm->delete();
            }
        }

        Auth::user()->tokens()->delete();

        return response()->json([
            'status'  => true,
            'message' => 'Successfully logged out'
        ]);
    }

    public function forgotPassword(Request $request) {
        $validator = Validator::make($request->all(), [
            'email' => 'required',
        ])->stopOnFirstFailure(true);

        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

        $user = User::where('email', $request->email)->first();
        \Log::info('user '.$user );
        if ($user != null){

            $digits          = 6;
            $otpToken        = rand(pow(10, $digits-1), pow(10, $digits)-1);
            $user->api_token = $user->createToken('API Token')->plainTextToken;
            $user->otp       = (string)$otpToken;
            $user->save();
            try {
                $extra = "Thank you for your request to reset your password. Use the following OTP to complete the password reset process.";
                $emailDesc = EmailTemplate::where('key', 'RESET_PASSWORD_OTP')->value('description');
                if($emailDesc != null){
                    $extra = $emailDesc;
                }
                $messageBody = $otpToken;
                $this->sendMessageToClient($messageBody, $user->email, $extra, $user->first_name);

            } catch (\Exception $ex){}

            // $data = array('otp' => $user->otp, 'token' => $user->api_token);
            return $this->success(array('api_token' => $user->api_token), 'OTP has been sent on your email.');
        }else{
            return $this->error('Your email is not registered. Please signup', 400);
        }
    }

    public function resetPassword(Request $request) {
        $validator = Validator::make($request->all(), [
            'password' => 'required|min:6|confirmed',

        ])->stopOnFirstFailure(true);
        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }
        $user = Auth::user();
        $user->password = Hash::make($request->password);
        $user->save();
        return $this->success([], 'Password Updated Successfully');

    }

    public function changePassword(Request $request) {
        $validator = Validator::make($request->all(),[
            "old_password" => "required",
            "password"     => "required|min:6",
        ])->stopOnFirstFailure(true);
        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

        $user = Auth::user();

        if(Hash::check($request->old_password, $user->password)) {

            $user->password = Hash::make($request->password);
            $user->save();

            return $this->success([], 'Password Updated Successfully');

        } else {
            return $this->error("Current Password not matched");
        }
    }

    public function unauthenticatedUser() {
        return $this->error('Unauthorized', 401);
    }

    public function updateNotificationStatus(Request $request){
        $user = User::with('company')->find(Auth::id());
        $user->is_notify = $request->val;
        $user->save();

        return $this->success($user, "Status Updated Successfully");
    }

    public function updateProfile(Request $request){
        $validator = Validator::make($request->all(),[
            "first_name"    => "required",
            "last_name"     => "required",
            // "phone"         => "required",

        ])->stopOnFirstFailure(true);
        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

        $user = User::with('company')->find(Auth::id());
        $user->first_name = $request->first_name ?? $user->first_name;
        $user->last_name = $request->last_name ?? $user->last_name;
        $user->phone = $request->phone ?? $user->phone;

        if($request->has('image') && $request->file('image') != null){
            $imagePath = $this->uploadFile($request->file('image'), 'uploads/users/');
            $user->profile_image = $imagePath['path'];
        }
        $user->save();

        return $this->success($user, "Profile Updated Successfully");
    }

    public function updateCompanyProfile(Request $request){
        $validator = Validator::make($request->all(),[
            "name"      => "required",
            "address"   => "required",
            "type"      => "required",
            "city"      => "required",
            // "state"     => "required",
            "country"   => "required",
        ])->stopOnFirstFailure(true);
        if ($validator->fails()){
            return $this->error('Validation Error', 400, [], $validator->errors()->first());
        }

        $user = User::with('company')->find(Auth::id());
        $user->first_name = $request->first_name ?? $user->first_name;
        $user->last_name = $request->last_name ?? $user->last_name;
        $user->phone = $request->phone ?? $user->phone;
        if($request->has('image') && $request->file('image') != null){
            $imagePath = $this->uploadFile($request->file('image'), 'uploads/users/');
            $user->profile_image = $imagePath['path'];
        }
        $user->save();

        $logo = $user->company->logo;
        if($request->has('logo') && $request->file('logo') != null){
            $logoPath = $this->uploadFile($request->file('logo'), 'uploads/users/');
            $logo = $logoPath['path'];
        }

        $companyData = array(
            'name' => $request->name,
            'address' => $request->address,
            'type' => $request->type,
            'city' => $request->city,
            'state' => $request->state,
            'country' => $request->country,
            'post_code' => $request->post_code,
            'description' => $request->description,
            'logo' => $logo
        );
        Company::where('user_id', Auth::id())->update($companyData);

        $user = User::with('company')->find(Auth::id());
        return $this->success($user, "Profile Updated Successfully");
    }

    public function deleteAccount(){

        $user = User::where('id', Auth::id())->first();
        $user->delete();
        return $this->success((object)array(), "Account Deleted Successfully");
    }

    public function socialLogin(Request $request){
        $check_user = User::with('company')->where('provider_id', $request->id)->first();

        if($check_user == null) {

            $digits   = 6;
            $otpToken =  rand(pow(10, $digits-1), pow(10, $digits)-1);
            $names = explode(' ', $request->name);

            $user = User::create([
                "role_id"   => 2,
                "password"  => Hash::make("1234@Social"),
                "phone"     => $request->phone,
                "email"     => $request->email,
                "first_name"=> $names[0] ?? $request->name ?? " - ",
                "last_name" => $names[1] ?? " ",
                "otp"       => $otpToken,
                "fcm_token" => $request->fcm_token ?? null,
                "company_type"=> null,
                "status"    => 1,
                "is_active" => 1,
                "is_notify" => 1,
                "has_company" => 0,
                "profile_image"=> $request->avatar,
                "provider_id" => $request->id,
                "provider_name" => $request->type,
                "company" => null,
            ]);
            $token           = $user->createToken('API Token')->plainTextToken;
            $user->api_token = $token;
            $user->save();

            return $this->success($user);
        } else {
            $check_user->fcm_token = $request->fcm_token;
            $check_user->is_active = 1;
            Auth::login($check_user);
            $check_user->api_token =  auth()->user()->createToken('API Token')->plainTextToken;
            $check_user->save();

            return $this->success($check_user);
        }
    }

    public function updateOnlineStatus(Request $request){
        $user = User::find(Auth::id());
        $user->is_active = $request->value;
        $user->save();

        return $this->success($user);
    }

    public function testNotification(Request $request){
        // $user = User::with('fcms')->find($request->user_id);
        $user = User::find($request->user_id);

        // $fcmTokens = $user->fcms->pluck('fcm_token')->toArray();

        if (!$user || $user->fcms->isEmpty()) {
            return $this->error([], 'No FCM tokens found for this user');
        }


        // NotificationHelper::sendAndStoreNotificationNew(
        //     $user->fcms,
        //     $user->id,
        //     'Test Notification',
        //     'This is a test notification from Trading FMCG App'
        // );

        NotificationHelper::sendNotificationNew(
            $user->fcms,
            "message",
            'Test Notification',
            'This is a test notification from Trading FMCG App'
        );

        return $this->success([], 'Notification Sent Successfully');
    }
}
