<?php

namespace App\Controllers;

use App\Libraries\CIAuth;
use App\Libraries\NemoSoftsAPI;
use App\Libraries\PasswordGenerator;
use App\Libraries\PasswordVerify;
use App\Libraries\EmailService;

use App\Models\CIAuthModel;
use App\Models\PanelModel;
use App\Models\AdminModel;

class AuthController extends BaseController {
    
    public function __construct(){
        $this->db = \Config\Database::connect();
        $panelModel = new PanelModel();
        $this->settings = $panelModel->getSettings();
        $this->details = new AdminModel();
    }

    public function index() {
        if(CIAuth::check()){
            return redirect()->to(base_url('ns-admin/dashboard'));
        } else {
            return redirect()->to(base_url('ns-admin/login'));
        }
    }
    
    public function loginForm() {
        if(CIAuth::check()){
            return redirect()->to(base_url('ns-admin/dashboard'));
        }
        
        $data = [
            'pageTitle' => 'Login',
            'validation' => null
        ];
        $data['settings'] = $this->settings;
        
        return view('login', $data);
    }
    
    public function loginHandler() {
        
        $username =  $this->request->getVar('user_login');
        $password = $this->request->getVar('nsofts_password_input');
        
        $adminModel = new CIAuthModel($this->db);
        $query = $adminModel->validateAdmin($username);
        
        if (!$query) {
            $message = array('message' => lang('Validation.login_failed'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin'));
        }
        
        if ($query->status == 0) {
            $message = array('message' => lang('Validation.registration_approve'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('/ns-admin'));
        }
     
        if (PasswordVerify::verify($password, $query->password)) {
            CIAuth::setCIAuth($query);
            return redirect()->to(base_url('ns-admin'));
        } else {
            $message = array('message' => lang('Validation.password_invalid'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin'));
        }
    }
    
    public function logout(){
        CIAuth::forget();
        $message = array('message' => lang('Validation.logout'),'class' => 'success');
        session()->set('response_msg', $message);
        return redirect()->to(base_url('ns-admin'));
    }
    
    // Forgot Password ---------------------------------------------------------
    public function registerForm(){
        $data = [
            'pageTitle' => 'Forgot Password',
            'validation' => null
        ];
        $data['settings'] = $this->settings;
        return view('auth_register', $data);
    }
    
    public function registerHandler(){
        
        $name =  $this->request->getVar('register_name');
        $email =  $this->request->getVar('register_email');
        $password =  $this->request->getVar('register_password');
        $confirmPassword =  $this->request->getVar('register_confirm_password');
        
        if($this->details->getUserByEmail($email)){
            $message = array('message' => lang('Validation.email_exist'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/register'));
        }
        
        if($confirmPassword != $password){
            $message = array('message' => lang('Validation.password_not_matched'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/register'));
        } else {
            
            $hashedPassword = PasswordVerify::hash($password);
            
            $data = array( 
                'username'  =>  $name,
                'email'  =>  $email,
                'admin_type'  =>  $this->request->getPost('admin_type'),
                'password'  =>  $hashedPassword,
                'image'  =>  '',
                'status' => '0'
            );
            $this->details->insert($data);
            
            $emailService = new EmailService();
            $toName   = 'Recipient Register';
            $subject = '[IMPORTANT] '.$this->settings['app_name'].' Registration Successful';
            $msg  = '<tr>
        		<img src="'.base_url('images/'.$this->settings['app_logo']).'" alt="header" />
        		</br>
        		<h1>Hello! '.$name.'</h1>
        		<p>'.lang('Validation.registration_approve').'</p>
        		<p>You can log in using this link: '.base_url('ns-admin').'</p>
        		<p>Thank you.</p>
        		';
            if ($emailService->sendEmail($email, $toName, $subject, $msg)) {
                
            }
            
            $message = array('message' => lang('Validation.registration_approve'),'class' => 'success');  
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin'));
        }
    }
    
    // Forgot Password ---------------------------------------------------------
    public function forgotPassword(){
        $data = [
            'pageTitle' => 'Register',
            'validation' => null
        ];
        $data['settings'] = $this->settings;
        return view('auth_pass_recovery', $data);
    }
    
    public function forgotPasswordHandler(){
        
        $email =  $this->request->getVar('forgot_email');
        $userData = $this->details->getUserByEmail($email);
        if($userData){
            
            $newPassword = bin2hex(random_bytes(4));
            
            $hashedPassword = PasswordVerify::hash($newPassword);
            
            $data = array(
                'password'  =>  $hashedPassword
            );
            $this->details->update($userData['id'], $data);
            
            $emailService = new EmailService();
            $toName   = 'Recipient Password Reset';
            $subject = '[IMPORTANT] '.$this->settings['app_name'].' Your Password Reset';
            $msg  = '<tr>
        		<img src="'.base_url('images/'.$this->settings['app_logo']).'" alt="header" />
        		</br>
        		<h1>Hello! '.$userData['username'].'</h1>
        		<p style="font-size: medium;">Your new password is:  <strong style="background-color: #e1e1e1; border-radius: 5px; 
        		color: #000; display: inline-block; font-weight: bold; padding-left: 10px; padding-right: 5px; padding-top: 5px; padding-bottom: 5px; font-size: large; letter-spacing: 5px;">
        		'.$newPassword.'
        		</strong></p>
        		<p>You can log in using this link: '.base_url('ns-admin').'</p>
        		<p>Please login and change your password immediately.</p>
        		<p>Thank you.</p>
        		';
            if ($emailService->sendEmail($userData['email'], $toName, $subject, $msg)) {
                $message = array('message' => lang('Validation.email_sent'),'class' => 'success');
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin'));
            } else {
                $message = array('message' => lang('Validation.email_sent_failed'),'class' => 'error');
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin/forgot-password'));
            }
        } else {
            $message = array('message' => lang('Validation.email_not_found'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/forgot-password'));
        }
    }
    
    // Profile -----------------------------------------------------------------
    public function profileForm(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $dataDetails = $this->details->find(CIAuth::id());
        
        $data = [
            'pageTitle' => 'Edit Profile',
            'currentFile' => 'edit_profile',
            'validation' => null,
            'user_id' => $dataDetails['id'],
            'row' => $dataDetails,
        ];
        
        $data['settings'] = $this->settings;
        return view('auth_profile', $data);
    }
    
    public function profileHandler(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $editID = CIAuth::id();
        if(empty($editID)){
            CIAuth::forget();
            $message = array('message' => lang('Validation.Login'),'class' => 'success');
            $session->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin'));
        }
        
        $dataDetails = $this->details->find($editID);
        if($dataDetails){
            if ($this->request->getPost('submit') !== null) {
                $imageName = $this->handleImageUpload($dataDetails['image']);
                $data = array( 
                    'username'  =>  $this->request->getPost('username'),
                    'email'  =>  $this->request->getPost('email'),
                    'image'  =>  $imageName,
                );
                $this->details->update($editID, $data);
                $message = array('message' => lang('Validation.updated'),'class' => 'success');
                CIAuth::forget();
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin'));
                
            } else if ($this->request->getPost('submit_password') !== null) {
                
                $confirmPassword = $this->request->getPost('register_confirm_password');
                $password = $this->request->getPost('register_password');
                
                if($confirmPassword != $password){
                    $message = array('message' => lang('Validation.password_not_matched'),'class' => 'error');
                    session()->set('response_msg', $message);
                    return redirect()->to(base_url('ns-admin/profile'));
                } else {
                    
                    $hashedPassword = PasswordVerify::hash($password);
                    
                    $data = array(
                        'password'  =>  $hashedPassword
                    );
                    $this->details->update($editID, $data);
                    $message = array('message' => lang('Validation.updated'),'class' => 'success');  
                    CIAuth::forget();
                    session()->set('response_msg', $message);
                    return redirect()->to(base_url('ns-admin'));
                }
            } else {
                $message = array('message' => lang('Validation.updated_failed'),'class' => 'error');
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin/profile'));
            }
        } else {
            $message = array('message' => lang('Validation.updated_failed_user'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/profile'));
        }
    }
    
    // Admin -------------------------------------------------------------------
    public function admin_index(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return redirect()->to(base_url('ns-admin'));
        }
        
        $data = [
            'pageTitle' => 'Manage Admin Users',
            'currentFile' => 'manage_admin',
            'tableName' => 'tbl_admin'
        ];
        
        $data['settings'] = $this->settings;
        
        $keyword = $this->request->getGet('keyword') ?? '';
        if (!empty($keyword)) {
            $data['result'] = $this->details
                ->orderBy('id', 'DESC')
                ->like('username', $keyword)
                ->orLike('email', $keyword)
                ->findAll();
        } else {
            $data['result'] = $this->details->orderBy('id', 'DESC')->findAll();
        }
        return view('manage_admin', $data);
    }
    
    public function create(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return redirect()->to(base_url('ns-admin'));
        }
        
        $data = [
            'pageTitle' => 'Create User',
            'currentFile' => 'manage_admin',
            'pageSave' => 'Create'
        ];
        $data['settings'] = $this->settings;
        return view('create_admin', $data);
    }
    
    public function edit($id = null){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return redirect()->to(base_url('ns-admin'));
        }
        
        $dataDetails = $this->details->find($id);
        
        $data = [
            'pageTitle' => 'Edit User',
            'currentFile' => 'manage_admin',
            'pageSave' => 'Save',
            'user_id' => $dataDetails['id'],
            'row' => $dataDetails,
        ];
        $data['settings'] = $this->settings;
        return view('create_admin', $data);
    }
    
    public function createAdminHandler(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return redirect()->to(base_url('ns-admin'));
        }
        
        $editID = $this->request->getPost('user_id');
        if(empty($editID)){
            
            $name = $this->request->getPost('username');
            $email = $this->request->getPost('email');
            if($this->details->getUserByEmail($email)){
                $message = array('message' => lang('Validation.email_exist'),'class' => 'error');
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin/create-admin/'));
            }
            
            $imageName = $this->handleImageUpload();
            
            $password = $this->request->getPost('password');
            $hashedPassword = PasswordVerify::hash($password);
            
            $data = array( 
                'username'  =>  $this->request->getPost('username'),
                'email'  =>  $this->request->getPost('email'),
                'admin_type'  =>  $this->request->getPost('admin_type'),
                'password'  =>  $hashedPassword,
                'image'  =>  $imageName,
                'status' => '1'
            );
            $this->details->insert($data);
            
            $emailService = new EmailService();
            $toName   = 'Recipient Register';
            $subject = '[IMPORTANT] '.$this->settings['app_name'].' Registration Successful';
            $msg  = '<tr>
        		<img src="'.base_url('images/'.$this->settings['app_logo']).'" alt="header" />
        		</br>
        		<h1>Hello! '.$name.'</h1>
        		<p>'.lang('Validation.registration').'</p>
        		<p>You can log in using this link: '.base_url('ns-admin').'</p>
        		<p>Thank you.</p>
        		';
            if ($emailService->sendEmail($email, $toName, $subject, $msg)) {
                
            }
            
            $message = array('message' => lang('Validation.added'),'class' => 'success');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/manage-admin'));
        
        } else {
            
            $dataDetails = $this->details->find($editID);
            if($dataDetails){
                if ($this->request->getPost('submit') !== null) {
                    $imageName = $this->handleImageUpload($dataDetails['image']);
                    $data = array( 
                        'username'  =>  $this->request->getPost('username'),
                        'email'  =>  $this->request->getPost('email'),
                        'admin_type'  =>  $this->request->getPost('admin_type'),
                        'image'  =>  $imageName,
                    );
                    $this->details->update($editID, $data);
                    $message = array('message' => lang('Validation.updated'),'class' => 'success');
                    
                } else if ($this->request->getPost('submit_password') !== null) {
                    
                    $confirmPassword = $this->request->getPost('register_confirm_password');
                    $password = $this->request->getPost('register_password');
                    
                    if($confirmPassword != $password){
                        $message = array('message' => lang('Validation.password_not_matched'),'class' => 'error');
                    } else {
                        $hashedPassword = PasswordVerify::hash($password);
                        $data = array(
                            'password'  =>  $hashedPassword
                        );
                        $this->details->update($editID, $data);
                        $message = array('message' => lang('Validation.updated'),'class' => 'success');  
                    }
                } else {
                    $message = array('message' => lang('Validation.updated_failed'),'class' => 'error');
                }
            } else {
                $message = array('message' => lang('Validation.updated_failed_user'),'class' => 'error');
            }
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/create-admin/'.$editID));
        }
    }
    
    public function delete($id = null){
        // Check if the user is authorized to perform the action
        if (!CIAuth::check()) {
            return $this->response->setJSON(['status' => 0, 'message' => 'Unauthorized']);
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return $this->response->setJSON(['status' => 0, 'message' => 'Unauthorized']);
        }
        
        // Validate ID
        if (is_null($id) || !is_numeric($id)) {
            return $this->response->setJSON(['status' => 0, 'message' => 'Invalid ID']);
        }
        
        // Check if the record exists
        $record = $this->details->find($id);
        if (!$record) {
            return $this->response->setJSON(['status' => 0, 'message' => 'Record not found']);
        }
        
        try {
            // Attempt to delete the record
            if ($this->details->delete($id)) {
                session()->set('response_msg', ['message' => lang('Validation.deleted'), 'class' => 'success']);
                return $this->response->setJSON(['status' => 1, 'message' => 'Delete successful']);
            } else {
                return $this->response->setJSON(['status' => 0, 'message' => 'Failed to delete']);
            }
        } catch (\Exception $e) {
            // Log and handle potential errors during deletion
            log_message('error', 'Error deleting record: ' . $e->getMessage());
            return $this->response->setJSON(['status' => 0, 'message' => 'An error occurred while deleting']);
        }
    }
    
    public function status($id = null){
        // Ensure user is authenticated
        if (!CIAuth::check()) {
            return $this->response->setStatusCode(401)
                ->setJSON(['status' => 0, 'msg' => 'Unauthorized']);
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return $this->response->setStatusCode(401)
                ->setJSON(['status' => 0, 'msg' => 'Unauthorized']);
        }
        
        // Validate ID
        if (is_null($id) || !is_numeric($id)) {
            return $this->response->setJSON(['status' => 0, 'msg' => 'Invalid ID']);
        }
        
        // Check if record exists
        $record = $this->details->find($id);
        if (!$record) {
            return $this->response->setJSON(['status' => 0, 'msg' => 'Record not found']);
        }
        
        // Ensure the request is a POST request
        if (!$this->request->is('post')) {
            return $this->response->setStatusCode(405)
                ->setJSON(['status' => 0, 'msg' => 'Method Not Allowed']);
        }
        
        try {
            $for_action = $this->request->getPost('for_action');
            $column = $this->request->getPost('column');
            
            // Update data
            $data = [$column => ($for_action === 'enable' ? '1' : '0')];
            $message = ($for_action === 'enable') ? lang('Validation.enabled') : lang('Validation.disabled');
            
            $this->details->update($id, $data);
            
            return $this->response->setJSON([
                'status' => 1,
                'action' => $for_action,
                'msg' => $message,
                'class' => 'success'
            ]);
        } catch (\Exception $e) {
            return $this->response->setJSON([
                'status' => 0,
                'msg' => 'An error occurred while updating the record'
            ]);
        }
    }
    
    // Verification ------------------------------------------------------------
    public function verification_index(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return redirect()->to(base_url('ns-admin'));
        }
        
        $data = [
            'pageTitle' => 'Verification',
            'currentFile' => 'verification'
        ];
        $data['settings'] = $this->settings;
        return view('verification', $data);
    }
    
    public function verificationHandler(){
        if(!CIAuth::check()){
            return redirect()->to(base_url('ns-admin/login'));
        }
        
        $allowedAdminTypes = [1, 3];
        if(!in_array(CIAuth::adminType(), $allowedAdminTypes)){
            return redirect()->to(base_url('ns-admin'));
        }
        
        $api = new NemoSoftsAPI();
        if(empty($api)){
            $message = array('message' => lang('Validation.extension_missing'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/verification'));
        }
        
        $envato = $api->verifyEnvatoPurchaseCode(trim($this->request->getPost('envato_purchase_code')));
        if (empty($envato['status'])) {
            $message = array('message' => lang('Validation.extension_missing'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/verification'));
        } else if($envato['status'] != true){
            $message = array('message' => lang('Validation.purchase_wrong'),'class' => 'error');
            session()->set('response_msg', $message);
            return redirect()->to(base_url('ns-admin/verification'));
        } else {
            
            $key = PasswordGenerator::generateStrongPassword();
            $apikey = $key;
            
            $verify = $api->verifyLicenseAndroid(trim($this->request->getPost('envato_purchase_code')), $apikey, trim($this->request->getPost('envato_package_name')));
            if (empty($verify['status'])) {
                $message = array('message' => lang('Validation.extension_missing'),'class' => 'error');
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin/verification'));
            } else {
                $data = array(
                    'envato_buyer_name' => trim($this->request->getPost('envato_buyer_name')),
                    'envato_purchase_code' => trim($this->request->getPost('envato_purchase_code')),
                    'envato_api_key' => $apikey,
                    'envato_package_name' => trim($this->request->getPost('envato_package_name'))
                );
                $panelModel = new PanelModel();
                $panelModel->update('1', $data);
                
                $message = array('message' => $verify['message'] ,'class' => 'success');
                session()->set('response_msg', $message);
                return redirect()->to(base_url('ns-admin/verification'));
            }
        }
    }

    private function handleImageUpload($existingImage = '') {
        $file = $this->request->getFile('image');
        if ($file->isValid() && !$file->hasMoved()) {
            if ($existingImage && file_exists("images/{$existingImage}")) {
                unlink("images/{$existingImage}");
            }
            $imageName = $file->getRandomName();
            $file->move('images/', $imageName);
            return $imageName;
        }
        return $existingImage;
    }
}
