<?php
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);

// sql-user-authenticate.php
require_once(htmlentities($_SERVER['DOCUMENT_ROOT']) . '/public/assets/php/definitions.php');

/**
 * Helper function to call a stored procedure and consume all result sets.
 * Returns the last fetched result as an object or null if no data.
 * Sets error messages in $return_data if call fails.
 */
function callStoredProcedure(mysqli $db, string $query, stdClass &$return_data, string $errorContext, bool $expectResult = true) {
    if (!$db->multi_query($query)) {
        $return_data->errMsg = "DB Call error: $errorContext " . $db->errno . ' ' . $db->error;
        $return_data->rtnMsg = 'There was an Error Processing Your Credentials. Please Try Again.';
        return false;
    }

    $lastResult = null;

    do {
        if ($result = $db->store_result()) {
            if ($expectResult) {
                $lastResult = $result->fetch_object();
            }
            $result->free();
        } else {
            if ($db->errno) {
                // If there is a DB error regardless of expectResult, return false
                $return_data->errMsg = "Result Set error: $errorContext " . $db->errno . ' ' . $db->error;
                if ($expectResult) {
                    $return_data->rtnMsg = 'Your Credentials do Not Match Those In Our Records. Please Try to Login Again.';
                } else {
                    $return_data->rtnMsg = 'Database error occurred.';
                }
                return false;
            }
            // No error and no result - continue
        }
    } while ($db->more_results() && $db->next_result());

    // If not expecting a result, return true to indicate success
    if (!$expectResult) {
        return true;
    }

    return $lastResult;
}

function authenticateAgent(array $data): string {
    // Sanitize and validate input
    $emaillogin = filter_var($data['username'] ?? '', FILTER_VALIDATE_EMAIL);
    $passwordlogin = filter_var($data['password'] ?? '', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    $pinlogin = filter_var($data['pinnumber'] ?? '', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    $iplogin = filter_var($data['iplogin'] ?? '', FILTER_SANITIZE_FULL_SPECIAL_CHARS);

    $return_data = new stdClass();
    $return_data->success = 0;
    $return_data->errMsg = '';
    $return_data->rtnMsg = '';
    $return_data->tracking = '';

    $error = false;

    // Connect to DB
    $db = new mysqli(PACKAGE_LOG_DB_SERVER, PACKAGE_LOG_DB_USER, PACKAGE_LOG_DB_PASS, PACKAGE_LOG_DB_NAME);

    // Check connection
    if ($db->connect_errno) {
        $return_data->errMsg = 'Database Connection error: ' . $db->connect_errno . ' ' . $db->connect_error;
        $error = true;
        $return_data->rtnMsg = 'An error has occurred while processing your form. Please try again.';
        $return_data->tracking = 'Connection to DB made';
    }

    // Reconstitute Encrypted Password
    if (!$error) {
        $emaillogin_esc = $db->real_escape_string($emaillogin);

        $auth = callStoredProcedure($db, "CALL Login_AgentPassHashReturn('$emaillogin_esc')", $return_data, 'Login_AgentPassHashReturn');
        if ($auth === false) {
            $error = true;
        } else {
            $salt = $auth->hash ?? null;
            $return_data->salt = $salt;

            if ($salt === null) {
                $return_data->errMsg = 'Salt is null';
                $return_data->rtnMsg = 'Your Credentials do Not Match Those In Our Records. Please Try to Login Again.';
                $error = true;
            }
        }
    }

    // Reconstitute encrypted password
    if (!$error) {
        $hashedpassword = HashPassword($passwordlogin, $salt);
        $return_data->hashedpassword = $hashedpassword;
    }

    // Check login attempts from agent's email account
    if (!$error) {
        $auth = callStoredProcedure($db, "CALL Login_IncrementAgentEmailAttempts('$emaillogin_esc')", $return_data, 'Login_IncrementAgentEmailAttempts');
        if ($auth === false) {
            $error = true;
        } else {
            $failedemailloginattempts = $auth->emailattempts ?? 0;
            $return_data->failedemailloginattempts = $failedemailloginattempts;

            if ($failedemailloginattempts >= MAX_EMAIL_LOGIN_ATTEMPTS) {
                $error = true;
                $return_data->rtnMsg = 'You Have Attempted to Login to This User Account Too Many Times. Please Contact the System Administrator to Reset Your Account.';
                $return_data->errMsg = "A customer has been blocked from further access attempts due to too many login attempts. IP Address: " . $iplogin . " Email: " . $emaillogin;
            }
        }
    }

    // Check IP login attempts
    if (!$error) {
        $iplogin_esc = $db->real_escape_string($iplogin);

        $auth = callStoredProcedure($db, "CALL Login_IncrementIPLoginAttempts('$iplogin_esc')", $return_data, 'Login_IncrementIPLoginAttempts');
        if ($auth === false) {
            $error = true;
        } else {
            $failediploginattempts = $auth->ipattempts ?? 0;
            $return_data->failediploginattempts = $failediploginattempts;

            if ($failediploginattempts >= MAX_IP_LOGIN_ATTEMPTS) {
                $error = true;
                $return_data->rtnMsg = 'You Have Attempted to Login to This User Account Too Many Times. Please Contact the System Administrator to Reset Your Account.';
                $return_data->errMsg = "A customer has been blocked from further access attempts due to too many login attempts. IP Address: " . $iplogin_esc . " Email: " . $emaillogin;
            }
        }
    }

    // Check Username and Password
    if (!$error) {
        $hashedpassword_esc = $db->real_escape_string($hashedpassword);
        $pinlogin_esc = $db->real_escape_string($pinlogin);

        $auth = callStoredProcedure($db, "CALL Login_AgentInfoReturn('$emaillogin_esc', '$hashedpassword_esc', '$pinlogin_esc')", $return_data, 'Login_AgentInfoReturn');
        if ($auth === false) {
            $error = true;
        } else {
            if (empty($auth->agent_key) || empty($auth->storename) || empty($auth->access) || empty($auth->store_key)) {
                $error = true;
                $return_data->errMsg = '<br><br>$customerinfo lacks required data<br>EmailLogin: '.$emaillogin.' <br>HashedPassword: '.$hashedpassword.'<br>Pin: '.$pinlogin;
                $return_data->rtnMsg = 'Your Credentials do Not Match Those In Our Records. Please Try to Login Again.';
            }
        }
    }

    // Reset Login Counters
    if (!$error) {
        // Ensure $userKey is an integer and valid
        $userKey = isset($auth->agent_key) ? (int)$auth->agent_key : 0;

        // Optional: Check if userKey is valid (non-zero)
        if ($userKey <= 0) {
            // Log or handle invalid user key error if needed
            $return_data->errMsg .= ' Invalid userKey detected for reset login attempts.';
            // You may choose to set $error = true; here if this is critical
        }

        // Call stored procedure to reset email login attempts
        if (!callStoredProcedure($db, "CALL Login_AgentResetEmailLoginAttempts('$emaillogin_esc', $userKey)", $return_data, 'Login_AgentResetEmailLoginAttempts', false)) {
            $return_data->errMsg .= ' DB Call error: Login_AgentResetEmailLoginAttempts';
        }

        // Call stored procedure to reset IP login attempts
        if (!callStoredProcedure($db, "CALL Login_AgentIPAttempts('$iplogin_esc')", $return_data, 'Login_AgentIPAttempts', false)) {
            $return_data->errMsg .= ' DB Call error: Login_AgentIPAttempts';
        }
    }

    // Customer Login Successful
    if (!$error) {
        $length_salt = 16;
        $random = genRandomString(null);
        $salt_ip = substr($random, 0, $length_salt);
        $useragent = filter_var($_SERVER["HTTP_USER_AGENT"], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        $hash_user = sha1($salt_ip . $iplogin . $useragent);
        $signature = $salt_ip . $hash_user;

        $franchise_key = $auth->franchise_key ?? '';
        $store_key = $auth->store_key ?? '';
        $agent_key = $auth->agent_key ?? '';

        $signature_esc = $db->real_escape_string($signature);
        $franchise_key_esc = isset($auth->franchise_key) ? (int)$auth->franchise_key : 0;
        $store_key_esc = isset($auth->store_key) ? (int)$auth->store_key : 0;
        $agent_key_esc = isset($auth->agent_key) ? (int)$auth->agent_key : 0;

        $return_data->tracking .= '<br>Store Signature.';
        if (!callStoredProcedure($db, "CALL Login_AgentStoreAuthorizedSignature('$iplogin_esc', '$signature_esc', $franchise_key_esc, $store_key_esc, $agent_key_esc)", $return_data, 'Login_AgentStoreAuthorizedSignature', false)) {
            $error = true;
            $return_data->tracking .= '<br>Store Signature Error';
        }
    }

    if ($db) {
        $db->close();
    }

    if (!$error) {
        $return_data->userinfo = $auth;
        $return_data->success = 1;
        $return_data->signature = $signature;
    }

    return json_encode($return_data);
}