<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Laravel\Passport\RefreshTokenRepository;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Role;
use App\Models\UsersRole;
use App\Models\UsersAddress;
use App\Models\UsersNumber;
use App\Models\UsersSubscription;
use App\Models\SubscriptionsPackage;
use Carbon\Carbon;
use Exception;
use Laravel\Socialite\Facades\Socialite;

class UsersController extends Controller
{
    
    protected $social_providers = [
        'google', 'facebook', 'linkedin'
    ];

    public function register(Request $request)
    {

        // echo "<pre>";
        // print_r($request->all());
        // exit();
        
        $validator = Validator::make($request->all(), [
            'firstname' => 'required|min:2',
            'lastname' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:8',
            'role_id' => 'required|numeric',
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }

        $role_id = $request->role_id;
        
        // create user with basic information
        $user = User::create([
            'user_prefix_id' => $request->user_prefix_id ?? null,
            'firstname' => $request->firstname,
            'middlename' => $request->middlename ?? '',
            'lastname' => $request->lastname,
            'user_suffix_id' => $request->user_suffix_id ?? null,
            'uuid' => (string) Str::uuid(),
            'email' => $request->email,
            'password' => bcrypt($request->password),
            'website_id' => 1,     // indicate that this user is from property website
        ]);
        
        $user_id = $user->id;
        
        // set this user role
        UsersRole::create([
            'user_id' => $user_id,
            'role_id' => $request->role_id,
        ]);
        
        // numbers
        $numbers = $request->numbers ?? [];

        foreach($numbers as $n){
            
            $update_criteria = [];
            if(!empty($b['id'])){
                $update_criteria['id'] = $n['id'];
            }
            else{
                $update_criteria['id'] = 0;
            }
            
            UsersNumber::updateOrCreate($update_criteria, [
                'user_id' => $user_id,
                'country_code' => $n['phone_country_code'] ?? '',
                'phone_number' => $n['phone_number'] ?? '',
                'number_type' => $n['number_type'] ?? '',
            ]);
            
        }
        
        // addresses
        $addresses = $request->addresses ?? [];

        foreach($addresses as $a){
            
            $update_criteria = [];
            if(!empty($b['id'])){
                $update_criteria['id'] = $a['id'];
            }
            else{
                $update_criteria['id'] = 0;
            }
            
            UsersAddress::updateOrCreate($update_criteria, [
                'user_id' => $user_id,
                'line1' => $a['address_line1'] ?? '',
                'line2' => $a['address_line2'] ?? '',
                'city' => $a['city'] ?? '',
                'state' => $a['state'] ?? '',
                'country' => $a['country'] ?? '',
                'zip_code' => $a['zip_code'] ?? ''
            ]);
            
        }
        
        // if user is owner
        if($role_id == 2){
            
            // start free subscription
            // $subscription_id = 1;   // trail account id
            // $subscription_package = SubscriptionsPackage::find($subscription_id)->toArray();
            // $no_of_days = $subscription_package['no_of_days'];

            // $start_date = date('d-m-Y');
            // $start_date_str = strtotime(date('d-m-Y')) + 1;
            // $end_date = date('d-m-Y', strtotime(date('d-m-Y') . ' +'.$no_of_days.' day'));
            // $end_date_str = strtotime(date('d-m-Y') . ' +'.$no_of_days.' day') + 1;

            // UsersSubscription::create([
            //     'user_id' => $user_id,
            //     'subscription_id' => $subscription_id,  // trail account id
            //     'price' => 0,
            //     'transaction_id' => '',
            //     'transaction_details' => json_encode(array()),
            //     'start_date' => $start_date,
            //     'start_date_str' => $start_date_str,
            //     'end_date' => $end_date,
            //     'end_date_str' => $end_date_str,
            // ]);

        }

        return response()->json(['data' => $user]);
    }
    
    public function login(Request $request)
    {
        $credentials = $request->only(['email', 'password']);
        $validator = Validator::make($credentials, [
            'email' => 'required|email',
            'password' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }

        if (!auth()->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        /* ------------ Create a new personal access token for the user. ------------ */
        $tokenData = auth()->user()->createToken('MyApiToken');
        $token = $tokenData->accessToken;
        $expiration = $tokenData->token->expires_at->diffInSeconds(Carbon::now());

        return response()->json([
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => $expiration
        ]);
    }

    public function getUser()
    {
        
        $user = auth()->user();
        
        $assigned_roles = User::find($user->id)->assignedRoles->toArray();
        $phone_numbers = User::find($user->id)->phoneNumbers->toArray();
        $addresses = User::find($user->id)->addresses->toArray();
        $subscriptions = User::find($user->id)->subscriptions->toArray();


        $user->assigned_roles = $assigned_roles;
        $user->phone_numbers = $phone_numbers;
        $user->addresses = $addresses;
        $user->subscriptions = $subscriptions;
        
        return response()->json(auth()->user());
    }

    public function logout()
    {
        $token = auth()->user()->token();

        /* --------------------------- revoke access token -------------------------- */
        $token->revoke();
        $token->delete();

        /* -------------------------- revoke refresh token -------------------------- */
        $refreshTokenRepository = app(RefreshTokenRepository::class);
        $refreshTokenRepository->revokeRefreshTokensByAccessTokenId($token->id);

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

    /* ----------------- get both access_token and refresh_token ---------------- */
    public function loginGrant(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
            'password' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }

        $baseUrl = url('/');
        $response = Http::post("{$baseUrl}/oauth/token", [
            'username' => $request->email,
            'password' => $request->password,
            'client_id' => config('passport.password_grant_client.id'),
            'client_secret' => config('passport.password_grant_client.secret'),
            'grant_type' => 'password'
        ]);

        $result = json_decode($response->getBody(), true);
        if (!$response->ok()) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        return response()->json($result);
    }

    /* -------------------------- refresh access_token -------------------------- */
    public function refreshToken(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'refresh_token' => 'required'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }

        $baseUrl = url('/');
        $response = Http::post("{$baseUrl}/oauth/token", [
            'refresh_token' => $request->refresh_token,
            'client_id' => config('passport.password_grant_client.id'),
            'client_secret' => config('passport.password_grant_client.secret'),
            'grant_type' => 'refresh_token'
        ]);

        $result = json_decode($response->getBody(), true);
        if (!$response->ok()) {
            return response()->json(['error' => $result['error_description']], 401);
        }
        return response()->json($result);
    }
    
    
    // -------------------------------------------------------------------------
    // ------------------------- Impersonation ---------------------------------
    // -------------------------------------------------------------------------
    
    public function impersonation(Request $request)
    {
        
        // print_r(auth());
        // exit();
        
        // echo $user_id = auth()->user()->id;
        // exit();
        // $owner_id = User::getOwnerOfUser($user_id);

        // // check if permission to do
        // if(!User::checkPermission('can-impersonate')){
        //     return response()->json(config('constants.messages.permission_denied'), 400);
        //     exit();
        // }
        
        $validator = Validator::make($request->all(), [
            'email' => 'required|email'
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $email = $request->email;
        
        $user = User::where(['email'=>$email])->first();
        
        if ($user) {
            
            
            
            $token = $user->createToken('Laravel Password Grant Client')->accessToken;
            return response()->json(['token'=>$token]);
        }
        else{
            return response()->json(['error' => 'Invalid User'], 401);
        }
        
    }
    
    
    
    //  ------------------------------------------------------------------------
    //  --------------------- social logins start ------------------------------
    //  ------------------------------------------------------------------------
    
    public function socialLogin(Request $request, $driver )
    {
        
        if(!in_array($driver, $this->social_providers) && config()->has("services.{$driver}")){
            return response()->json(['error' => "Login with $driver not allowed"], 401);
        }
        
//        $access_token = "ya29.A0AVA9y1v2ac0VucbqsttZ5MY7cAABfDzNA8matCsd2xFSdcSTMCI_st6NoQBmRvGRCgyZ2gC6ZY4PFefFSc0hcJubxjxQ8I-FLkqFgK06g7AmsvuVIdjW-ltiMxK9KSjRnTrtV6HWucEx2EjOJ4QWc2cn6YEpDwYUNnWUtBVEFTQVRBU0ZRRTY1ZHI4bHR4T2NpdVY5STBMSVZ0cGdzYUdFZw0165";
        $access_token = $request->query('token');
        
        try {
            $user = Socialite::driver($driver)->userFromToken($access_token);
            
            echo "<pre>";
            print_r($user);
            exit();
            
            // check for email in returned user
            if(empty($user->email)){
                return response()->json(['error' => "No email id returned from {$driver} provider."], 401);
            }
            
            echo $user['name'];
            echo ' ';
            echo $user['email'];
            exit();
            echo "<pre>";
            print_r($user);
            exit();
            
        } catch (Exception $e) {
            //return $this->sendFailedResponse($e->getMessage());
            return response()->json(['error' => $e->getMessage()], 401);
        }

        
    }
    
    //  ------------------------------------------------------------------------
    //  --------------------- social logins end --------------------------------
    //  ------------------------------------------------------------------------
    
    
    public function getAllRoles()
    {
        
        $user_id = auth()->user()->id;

        // check if permission to do
        if(!User::checkPermission('get-all-roles')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $roles = Role::all();
        
        return response()->json(['message' => config('constants.messages.response_success'), 'data'=> ['roles' => $roles] ]);
    }
    
    public function markUsersAsActive(Request $request){
        
        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);
        
        // check if permission to do
        if(!User::checkPermission('mark-users-as-active')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        // print_r($request->all());
        // exit();
        
        $validator = Validator::make($request->all(), [
            'ids' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $ids = $request->ids;
        
        foreach($ids as $id){
            User::where(['id'=>$id])->update(['is_active'=>1]);
        }
        
        return response()->json(['message' => 'Updated Successfully']);
        
    }
    
    public function markUsersAsInactive(Request $request){
        
        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);
        
        // check if permission to do
        if(!User::checkPermission('mark-users-as-inactive')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $validator = Validator::make($request->all(), [
            'ids' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $ids = $request->ids;
        
        foreach($ids as $id){
            User::where(['id'=>$id])->update(['is_active'=>0]);
        }
        
        return response()->json(['message' => 'Updated Successfully']);
        
    }
    
    public function deleteOwnersUsers(Request $request){

        // check if permission to do
        if(!User::checkPermission('delete-owners-users')){
            return response()->json(config('constants.messages.permission_denied'), 400);
            exit();
        }
        
        $user_id = auth()->user()->id;
        $owner_id = User::getOwnerOfUser($user_id);
        
        
        $validator = Validator::make($request->all(), [
            'ids' => 'required'
        ]);
        
        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }
        
        $ids = $request->ids ?? [];
        
        foreach($ids as $u_id){
            $user = User::find($u_id);
            // print_r($user);
            // exit();
            if(!empty($user)){
                if($user->owner_id == $owner_id && $user->is_active == 0){
                    User::find($u_id)->delete();
                }
            }
            
        }
        
        return response()->json(['message' => 'Deleted', 'data'=> [] ]);

    }
    
    
}