<?php

namespace App\Http\Auth;

use SelfPhp\SP; 
use SelfPhp\Auth;
use SelfPhp\Request; 
use SelfPhp\SPException; 
use App\Models\AuthModel;
use App\Http\Utils\AuthUtil; 
use App\Services\MailerService;
use App\Http\Middleware\AuthMiddleware;

/**
 * Class AuthController
 * Handles authentication-related actions such as login, signup, and logout.
 */
class AuthController extends SP
{ 
    /**
     * @var AuthUtil
     */
    public $authUtil; 

    /**
     * AuthController constructor.
     *
     * @param AuthUtil $authUtil An instance of AuthUtil for authentication utility functions.
     */
    public function __construct(AuthUtil $authUtil) 
    {
        $this->authUtil = $authUtil;
    }

    /**
     * Displays the login view.
     *
     * @return string The HTML content of the login view.
     */
    public function login()
    { 
        return view("auth.login");
    }

    /**
     * Displays the signup view.
     *
     * @return string The HTML content of the signup view.
     */
    public function signup()
    {
        return view("auth.register");
    }

    /**
     * Handles the user login process.
     *
     * @param Request $request The HTTP request object.
     * @return string A route indicating the login status and message.
     */
    public function login_user(Request $request)
    {
        try { 
            // Validate input fields from the request
            $req = $request->captureAll(); 
            
            if (!$req['email'] || !$req['password']) { 
                throw new SPException("Email and Password are required!");
            }

            $data['email'] = $req['email'];
            $data['password'] = $req['password'];

            // Check if the user exists
            $user = $this->authUtil->checkUser($data); 

            if (empty($user)) { 
                throw new SPException("No account associated with the email found!");
            }

            // Check if the email matches
            if ($user['email'] !== $data['email']) {
                throw new SPException("Please check your username and password, and try again!!!");
            }

            // Verify the password
            if (!Auth::verify_pass($data['password'], $user['password'])) { 
                throw new SPException("Please check your username and password, and try again!");
            }
            
            // Start session if login is successful
            $userSessionData = [
                'user_id' => $user['id'],
                'uuid' => $user['uuid'],
                'name' => ucwords(strtolower($user['name'])),
                'username' => strtolower($user['username']),
                'email' => $user['email'],
                'contact' => $user['contact'],
                'profile_photo' => $user['profile_photo'],
                'is_verified' => $user['is_verified'],
                'accountType' => $user['accountType'],
                // 'settings' => $settings ?? []
            ];

            Auth::start_session($userSessionData); 

            $route = '/dashboard';
            $token = Auth::generate_token($userSessionData);

            return ['status' => 'success', 'token' => $token, 'route' => $route];
        } catch (SPException $e) { 
            return ['status' => 'error', 'code' => $e->getCode() ?: 401, 'message' => $e->getMessage()];
        } catch(\Exception $e) { 
            return ["status" => "error", 'code' => $e->getCode() ?: 401, "message" => sp_error_logger($e->getMessage())];  
        }
    }

    /**
     * Handles the user signup process.
     *
     * @param Request $request The HTTP request object.
     * @return string A route indicating the signup status and message.
     */
    public function signup_user(Request $request)
    { 
        try { 
            $data = $request->captureAll();  

            if (empty($data['terms']) || !$data['terms']) {
                throw new SPException("You must accept the terms and conditions to continue!");
            }

            // Check name
            if (empty($data['name'])) {
                throw new SPException("The name field is required!");
            }

            // Check username
            if (empty($data['username'])) {
                throw new SPException("The username field is required!");
            }

            // Check email
            if (empty($data['email'])) {
                throw new SPException("The email field is required!");
            }

            // Check password
            if (empty($data['password'])) {
                throw new SPException("The password field is required!");
            }

            // Check if user already exists
            if ($this->authUtil->checkUser($data)) { 
                throw new SPException("User is already registered. Register using a different email!");
            }
            
            $register = $this->authUtil->registerUser($data);
            if ($register) {  
                return ["status" => "success", 'route' => '/login'];
            }
            
            throw new SPException("Server Error! Please try again later.");
        } catch (SPException $e) { 
            return ["status" => "error", 'code' => $e->getCode() ?: 401, "message" => $e->getMessage()];
        } catch(\Exception $e) { 
            return ["status" => "error", 'code' => $e->getCode() ?: 401, "message" => sp_error_logger($e->getMessage())];
        }
    }

    /**
     * Logs the user out of the system.
     *
     * @return string A route indicating the logout status and message.
     */
    public function logout()
    {
        try {
            if (Auth::auth() == true) {
                if (Auth::boot_out() == true) {
                    return route("login?#booted out", ["status" => "warning", "message" => "You have been logged out!"]);
                } else {
                    throw new SPException("System error when trying to log you out!");
                }
            } else {
                return route("login?#booted out", ["status" => "warning", "message" => "Login required!"]);
            }
        } catch (SPException $e) { 
            return route("dashboard", ["status" => "error", "message" => $e->getMessage()]);
        } catch (\Exception $e) { 
            return route("dashboard", ["status" => "error", "message" => sp_error_logger($e->getMessage())]);
        }
    }
}
