<?php

namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
use App\Models\UserModel;
use App\Models\OrganizationModel;
use App\Models\GroupModel;
use App\Models\PolicyModel;
use App\Models\PolicyDetailsModel;
use App\Models\ServiceModel;

use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use TheNetworg\OAuth2\Client\Provider\Azure;
use Google\Client as GoogleClient;
use Google\Service\Oauth2;

class AuthController extends ResourceController
{
    protected $format = 'json';
    protected $userModel;
    protected $organizationModel;
    protected $groupModel;
    protected $policyModel;
    protected $policyDetailsModel;
    protected $serviceModel;
    protected $provider;
    protected $googleProvider;

    public function __construct()
    {
        helper('jwt_helper');
        helper('oauth_helper');
        $this->userModel = new UserModel();
        $this->organizationModel = new OrganizationModel();
        $this->groupModel = new GroupModel();
        $this->policyModel = new PolicyModel();
        $this->policyDetailsModel = new PolicyDetailsModel();
        $this->serviceModel = new ServiceModel();

        $this->provider = new Azure([
            'clientId'     => "9af66888-eb85-48ec-b3a0-ba857734f52b",
            'clientSecret' => "N2_8Q~FBEXtoZft2UgJ6FQZCh3ZIbJydYgxREbUb",
            // 'redirectUri'  => "https://apitest.tripapprovaltool.com/tstat/authredirection",
            // 'redirectUri'  => "https://apitest.tripapprovaltool.com/tstat_be/auth/msRedirectionHandler",
            'redirectUri'  => env('MS_REDIRECTION_URL'),
            'tenant'       => "284bf2b6-6dd8-4b46-881c-de45fde35736",
        ]);
        $this->provider->scope = [
            'openid',
            'profile',
            'email',
            'offline_access',
            'User.Read'
        ];
        
    }

    public function login()
    {
        
        $data = $this->request->getJSON();

        // Decrypt payload if encryption is enabled (handled in Part 2 below)
        if (isset($data->encrypted) && $data->encrypted === true) {
            // $data = decryptLoginPayload($data->payload);

            $key = '1234567890123456'; // same as Flutter key
            $iv  = 'abcdefghijklmnop'; // same IV

            $cipher = 'AES-128-CBC';
            $decrypted = openssl_decrypt(base64_decode($data->payload), $cipher, $key, OPENSSL_RAW_DATA, $iv);

            $data =  json_decode($decrypted);
        }

        $user = $this->userModel->where('email', $data->email)->where('is_active',1)->first();
        // print_r($user);die;
        if (!$user) {
            return $this->failUnauthorized('Invalid email or password');
        }

        // Check if account is locked
        if (!empty($user['lock_until']) && strtotime($user['lock_until']) > time()) {
            $remaining = ceil((strtotime($user['lock_until']) - time()) / 60);
            return $this->failUnauthorized("Account locked. Try again in {$remaining} minutes.");
        }

        // If lock time expired, reset it
        if (!empty($user['lock_until']) && strtotime($user['lock_until']) <= time()) {
            $this->userModel->update($user['user_id'], [
                'failed_attempts' => 0,
                'lock_until' => null
            ]);
            $user['failed_attempts'] = 0;
            $user['lock_until'] = null;
        }
    
        // Password verification
        if (!password_verify($data->password, $user['password'])) {
            // Increment failed attempts
            $attempts = $user['failed_attempts'] + 1;
            $updateData = ['failed_attempts' => $attempts];

            // Lock account after 3 wrong attempts
            if ($attempts >= 3) {
                $updateData['lock_until'] = date('Y-m-d H:i:s', strtotime('+15 minutes'));
                $updateData['failed_attempts'] = 0; // reset after lock
            }

            $this->userModel->update($user['user_id'], $updateData);

            $msg = ($attempts >= 3)
                ? 'Too many failed attempts. Account locked for 30 minutes.'
                : 'Invalid email or password';
            return $this->failUnauthorized($msg);
        }

        //store last login
        $lastLoginBeforeUpdate = $user['last_login_at'];

         // Reset failed attempts after successful login
        $this->userModel->update($user['user_id'], [
            'failed_attempts' => 0,
            'lock_until' => null,
            'last_login_at' => date('Y-m-d H:i:s')
        ]);

        // Format date for FE
        $user = $this->userModel->select('user_id,first_name,last_name,role_id,org_id,group_id,last_login_at,agent_supported_service_ids')->where('email', $data->email)->first();
        $user['last_login_at'] = empty($lastLoginBeforeUpdate)
            ? null
            : date('d, M-Y h:iA', strtotime($lastLoginBeforeUpdate));

        //get role 
        $user['role'] = $this->userModel->getRole($user['role_id']);
            
        if($user['role_id'] != 5)
        {

            //get service for the organization
            $orgService = $this->organizationModel->find($user['org_id']);
            $user['service'] = json_decode($orgService['services_ids'],true);
            foreach ($user['service'] as $key => $value) 
            {
                $serviceData = $this->serviceModel->find($value['service_id']);
                $user['service'][$key]['name'] = $serviceData['name'];
                $user['service'][$key]['icon'] = $serviceData['icon'];
                $user['service'][$key]['order'] = $serviceData['order'];
            }

            //find user has the all access 
            $user['plan_action'] = getUserPlanCreationRestrictionStatus($user);

        }else{

            $user['service'] = json_decode($user['agent_supported_service_ids'],true);
            foreach ($user['service'] as $key => $value) 
            {
                $serviceData = $this->serviceModel->find($value['service_id']);
                $user['service'][$key]['name'] = $serviceData['name'];
                $user['service'][$key]['icon'] = $serviceData['icon'];
                $user['service'][$key]['order'] = $serviceData['order'];
            }

        }

        
        
    
        // Generate JWT Token
        $token = generateJWT($user);

        // Store the token in DB for current session
        $this->userModel->update($user['user_id'], [
            'current_token' => $token
        ]);
        
    
        return $this->respond([
            'status' => 200,
            'message' => 'Login successful',
            'token' => $token
        ]);
    }

    public function oauthClient()
    {
        $orgData = $this->organizationModel->find(env('ORG_id'));

        if (!$orgData) {  return $this->failUnauthorized('Organization Id Not Set'); }

        return $this->respond([
            'status' => 200,
            'message' => 'success',
            'data' => ['oauth_client_id' => $orgData['oauth_client_id'] , 'oauth_client_secret' => $orgData['oauth_client_secret']]
        ]);
        
    }

    public function oauthlogin()
    {
        $rules = [
            'email'    => 'required|valid_email',
            'name'      => 'required',
        ];
    
        if (!$this->validate($rules)) {
            return $this->failValidationErrors($this->validator->getErrors());
        }
    
       
        $data = $this->request->getJSON();
        $user = $this->userModel->where('email', $data->email)->first();
        
        if (!$user) {
            $insert['email'] = $data->email;
            $insert['first_name'] = $data->name;
            $insert['org_id'] = env('ORG_id');
            $insert['role_id'] = 4;
            $userId = $this->userModel->insert($insert, true);
            $user = $this->userModel->where('user_id', $userId)->first();
        }
    
        //get service for the organization
        $orgService = $this->organizationModel->find($user['org_id']);
        $user['service'] = json_decode($orgService['services_ids'],true);
        foreach ($user['service'] as $key => $value) 
        {
            $serviceData = $this->serviceModel->find($value['service_id']);
            $user['service'][$key]['name'] = $serviceData['name'];
            $user['service'][$key]['icon'] = $serviceData['icon'];
        }

        //get role 
        $user['role'] = $this->userModel->getRole($user['role_id']);

        //find user has the all access 
        $user['plan_action'] = getUserPlanCreationRestrictionStatus($user);
    
        // Generate JWT Token
        $token = generateJWT($user);
        
    
        return $this->respond([
            'status' => 200,
            'message' => 'Login successful',
            'token' => $token
        ]);
    }

    //microsoft oAuth
    public function mslogin()
    {   
        $options = [
            'scope' => ['openid', 'email', 'profile', 'User.Read']
        ];

        $authUrl = $this->provider->getAuthorizationUrl($options);

        return $this->response->setJSON([
            'auth_url' => $authUrl
        ]);
    }

   

    public function verifyMSAuthUser()
    {
        
        $code    = $this->request->getVar('code');
        // echo $code; 
        try {
            $token = $this->provider->getAccessToken('authorization_code', [
                'code' => $code
            ]);
            
            $ownerDetails = $this->provider->getResourceOwner($token);
            $data = $ownerDetails->toArray();

            $name = $data['name'] ?? null;
            $email = $data['upn'] ?? $data['unique_name'] ?? null;
            
            $res = checkUserExist($name, $email);

            if($res['status'] == true)
            { 
                $user = $res['data'];
                //get service for the organization
                $orgService = $this->organizationModel->find($user['org_id']);
                $user['service'] = json_decode($orgService['services_ids'],true);
                foreach ($user['service'] as $key => $value) 
                {
                    $serviceData = $this->serviceModel->find($value['service_id']);
                    $user['service'][$key]['name'] = $serviceData['name'];
                    $user['service'][$key]['icon'] = $serviceData['icon'];
                }
        
                //get role 
                $user['role'] = $this->userModel->getRole($user['role_id']);
        
                //find user has the all access 
                $user['plan_action'] = getUserPlanCreationRestrictionStatus($user);

                $token = generateJWT($user);

                return $this->respond([ 'status' => 200,'message' => 'Login successful','token' => $token ]);

            }else{
                return $this->respond([ 'status' => 401,'message' => 'Login Failed','data' => [] ]);
            }


            

        } catch (IdentityProviderException $e) {
            exit($e->getMessage());
        }
        
    }
    //end of microsoft oAuth


    public function receiveGoogleOAuthResponse()
    {
        
        if ($this->request->getGet('code')) {

            $value = googleOAuthLogin($this->request->getGet('code'));
            if ($value) {

                $user = $this->userModel->where('email', $value->email)->first();
                // print_r($user);die;
                if (empty($user)) {
                    return $this->failUnauthorized('User Not Found');
                }

                if ($user['is_active'] == 0) {
                    return $this->failUnauthorized('User Not Active');
                }
                    
                //get service for the organization
                $orgService = $this->organizationModel->find($user['org_id']);
                $user['service'] = json_decode($orgService['services_ids'],true);
                foreach ($user['service'] as $key => $value) 
                {
                    $serviceData = $this->serviceModel->find($value['service_id']);
                    $user['service'][$key]['name'] = $serviceData['name'];
                    $user['service'][$key]['icon'] = $serviceData['icon'];
                    $user['service'][$key]['order'] = $serviceData['order'];
                }
        
                //get role 
                $user['role'] = $this->userModel->getRole($user['role_id']);
        
                //find user has the all access 
                $user['plan_action'] = getUserPlanCreationRestrictionStatus($user);
            
                // Generate JWT Token
                $token = generateJWT($user);
                
            
                return $this->respond([
                    'status' => 200,
                    'message' => 'Login successful',
                    'token' => $token
                ]);
            }
        } else {
            return $this->respond([
                'status' => 400,
                'message' => 'Login failed',
            ]);
        }
    }

    public function initiateGoogleOAuth()
    {   
        return googleOAuthLogin(false);
    }

    public function msRedirectionHandler()
    {
        $FeURL = env('FE_URL') . '#/authredirection?code=' . $this->request->getGet('code');

        return redirect()->to($FeURL);
    }


    //re-Fetch token

    public function refreshUserToken()
    {
        

        $user_id = $this->request->getGet();
        $user = $this->userModel->select('user_id,first_name,last_name,role_id,org_id,group_id,last_login_at')->where('user_id', $user_id)->where('is_active',1)->first();
        // print_r($user);die;
        if (!$user) {
            return $this->failUnauthorized('Invalid User');
        }
    
      
        //get service for the organization
        $orgService = $this->organizationModel->find($user['org_id']);
        $user['service'] = json_decode($orgService['services_ids'],true);
        foreach ($user['service'] as $key => $value) 
        {
            $serviceData = $this->serviceModel->find($value['service_id']);
            $user['service'][$key]['name'] = $serviceData['name'];
            $user['service'][$key]['icon'] = $serviceData['icon'];
            $user['service'][$key]['order'] = $serviceData['order'];
        }

        //get role 
        $user['role'] = $this->userModel->getRole($user['role_id']);

        //find user has the all access 
        $user['plan_action'] = getUserPlanCreationRestrictionStatus($user);

        // print_r($user['plan_action']); die;
    
        // Generate JWT Token
        $token = generateJWT($user);

        // Store the token in DB for current session
        $this->userModel->update($user['user_id'], [
            'current_token' => $token
        ]);
        
        return $this->respond([
            'status' => 200,
            'message' => 'Login successful',
            'token' => $token
        ]);
    }


    public function logout()
    {
        $user_id = $this->request->getGet('user_id');
        $headerToken = $this->request->getHeaderLine('Authorization'); // Get the full header
    
        // Remove "Bearer " prefix if present
        $token = null;
        if (!empty($headerToken)) {
            $token = str_replace('Bearer ', '', $headerToken);
        }
    
        // Validate user existence and active status
        $user = $this->userModel->where('user_id', $user_id)->where('is_active', 1)->first();
    
        if (!$user) {
            return $this->respond([
                'status'  => 404,
                'message' => 'User not found or inactive'
            ], 404);
        }
    
        // Check token match
        if ($user['current_token'] !== $token) {
            return $this->respond([
                'status'  => 200,
                'message' => 'Unknown login or invalid token'
            ], 200);
        }
    
        // Token matches — logout success
        $this->userModel->update($user_id, ['current_token' => null]);
    
        return $this->respond([
            'status'  => 200,
            'message' => 'Logout successful'
        ], 200);
    }
    




//old login code
    // public function login() { $rules = [ 'email' => 'required|valid_email', 'password' => 'required' ]; if (!$this->validate($rules)) { return $this->failValidationErrors($this->validator->getErrors()); } $data = $this->request->getJSON(); $user = $this->userModel->where('email', $data->email)->where('is_active',1)->first(); // print_r($user);die; if (!$user) { return $this->failUnauthorized('Invalid email or password'); } // Verify password (assuming it's hashed) if (!password_verify($data->password, $user['password'])) { return $this->failUnauthorized('Invalid email or password'); } //update last login time in last_login_at column $this->userModel->update($user['user_id'], ['last_login_at' => date('Y-m-d H:i:s')]); $user = $this->userModel->where('email', $data->email)->first(); if (!empty($user['last_login_at'])) { $user['last_login_at'] = date('d, M-Y h:iA', strtotime($user['last_login_at'])); } else { $user['last_login_at'] = null; } //get service for the organization $orgService = $this->organizationModel->find($user['org_id']); $user['service'] = json_decode($orgService['services_ids'],true); foreach ($user['service'] as $key => $value) { $serviceData = $this->serviceModel->find($value['service_id']); $user['service'][$key]['name'] = $serviceData['name']; $user['service'][$key]['icon'] = $serviceData['icon']; $user['service'][$key]['order'] = $serviceData['order']; } //get role $user['role'] = $this->userModel->getRole($user['role_id']); //find user has the all access $user['plan_action'] = getUserPlanCreationRestrictionStatus($user); // Generate JWT Token $token = generateJWT($user); return $this->respond([ 'status' => 200, 'message' => 'Login successful', 'token' => $token ]); }



}
