<?php
use EnneoSDK\Api;
use EnneoSDK\Helpers;
use EnneoSDK\IntentInfo;
use EnneoSDK\IntentOption;
use EnneoSDK\Interaction;
require(getenv()['SDK'] ?? 'sdk.php');
/** @var stdClass $in */
######### Expected Input:
// date -> Date for deposit change (optional)
// channel -> ticket channel. Voice and chat can be handled synchronously (required)
// newIBAN -> IBAN of the new bank account (required)
// oldIBAN -> IBAN of the old bank account (optional)
// payoutOnly -> true if only payout should be changed (optional)
// Initialize variables
if ($in->date ?? false) {
    $in->date = Helpers::parseDateToYMD($in->date);
} else {
    $in->date = date('Y-m-d', strtotime('+1 day'));
}
$interaction = new Interaction(data: $in);
$interaction->data->oldIBAN = formatIban($in->oldIBAN ?: "");
$interaction->data->newIBAN = formatIban($in->newIBAN ?: "");
// Handle actual change of bank data in the backend system
if ($in->_action == 'enter_into_system') {
    $response = Api::call(
        method: 'POST',
        url: 'https://echo.enneo.ai',
        params: json_decode(json_encode($interaction), true)
    );
    echo json_encode($interaction);
    exit();
}
// Business logic
if ($in->oldIBAN == $in->newIBAN && $in->newIBAN) {
    $interaction->infos[] = new IntentInfo(
        type: 'warning',
        message: 'IBAN ist schon im System',
    );
    $interaction->options[] = new IntentOption(
        type: 'iban_already_in_system',
        name: 'Kunden darauf hinweisen',
        recommended: true,
    );
} elseif (!validateIbanFormatting($in->newIBAN)) {
    $interaction->infos[] = new IntentInfo(
        type: 'warning',
        message: 'IBAN nicht im korrekten Format',
    );
    $interaction->options[] = new IntentOption(
        type: 'ask_for_verification_iban_invalid_format',
        name: 'Kunden darauf hinweisen',
        recommended: true,
    );
} elseif (!validateIbanChecksum($in->newIBAN)) {
    $interaction->infos[] = new IntentInfo(
        type: 'warning',
        message: 'IBAN-Prüfsumme ungültig',
    );
    $interaction->options[] = new IntentOption(
        type: 'ask_for_verification_iban_invalid_checksum',
        name: 'Kunden darauf hinweisen',
        recommended: true,
    );
} else {
    if ($in->date < date('Y-m-d')) {
        // If the customer wants to use an IBAN effective in the past, we default to tomorrow
        $interaction->infos[] = new IntentInfo(
            type: 'warning',
            message: 'Gewünschtes Gültigkeitsdatum '.EnneoSDK\Helpers::formatDate($in->date).' liegt in der Vergangenheit. Gültigkeit auf morgen gesetzt'
        );
        $interaction->data->date = date('Y-m-d', strtotime('+1 day'));
    }
    $interaction->infos[] = new IntentInfo(
        type: 'success',
        message: 'IBAN gültig',
    );
    if ($in->payoutOnly) {
        $msg = 'Im System  nur für Guthaben hinterlegen';
    } else {
        $msg = 'Im System hinterlegen';
    }
    $interaction->options[] = new IntentOption(
        type: 'enter_into_system',
        name: $msg,
        recommended: true,
    );
}
// Return result
echo json_encode($interaction);
// Format IBAN for readability
function formatIban(string $iban): string
{
    $iban = str_replace(' ', '', $iban);
    // Split the input string into 4-character chunks for readability
    $formatted_iban = '';
    $chunk_size = 4;
    $num_chunks = ceil(strlen($iban) / $chunk_size);
    for ($i = 0; $i < $num_chunks; ++$i) {
        $chunk = substr($iban, $i * $chunk_size, $chunk_size);
        $formatted_iban .= $chunk . ' ';
    }
    // Trim any trailing spaces and return the formatted IBAN
    return trim($formatted_iban);
}
// Check integrity of IBAN (modified from original source: https://stackoverflow.com/questions/20983339/validate-iban-php)
function validateIbanChecksum(string $iban): bool
{
    $iban = strtolower(str_replace(' ', '', $iban));
    $Countries = ['al' => 28, 'ad' => 24, 'at' => 20, 'az' => 28, 'bh' => 22, 'be' => 16, 'ba' => 20, 'br' => 29, 'bg' => 22, 'cr' => 21, 'hr' => 21, 'cy' => 28, 'cz' => 24, 'dk' => 18, 'do' => 28, 'ee' => 20, 'fo' => 18, 'fi' => 18, 'fr' => 27, 'ge' => 22, 'de' => 22, 'gi' => 23, 'gr' => 27, 'gl' => 18, 'gt' => 28, 'hu' => 28, 'is' => 26, 'ie' => 22, 'il' => 23, 'it' => 27, 'jo' => 30, 'kz' => 20, 'kw' => 30, 'lv' => 21, 'lb' => 28, 'li' => 21, 'lt' => 20, 'lu' => 20, 'mk' => 19, 'mt' => 31, 'mr' => 27, 'mu' => 30, 'mc' => 27, 'md' => 24, 'me' => 22, 'nl' => 18, 'no' => 15, 'pk' => 24, 'ps' => 29, 'pl' => 28, 'pt' => 25, 'qa' => 29, 'ro' => 24, 'sm' => 27, 'sa' => 24, 'rs' => 22, 'sk' => 24, 'si' => 19, 'es' => 24, 'se' => 24, 'ch' => 21, 'tn' => 24, 'tr' => 26, 'ae' => 23, 'gb' => 22, 'vg' => 24];
    $Chars = ['a' => 10, 'b' => 11, 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17, 'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23, 'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29, 'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35];
    if (!array_key_exists(substr($iban, 0, 2), $Countries)) {
        return false;
    }
    if (strlen($iban) == $Countries[substr($iban, 0, 2)]) {
        $MovedChar = substr($iban, 4) . substr($iban, 0, 4);
        $MovedCharArray = str_split($MovedChar);
        $NewString = '';
        foreach ($MovedCharArray as $key => $value) {
            if (!is_numeric($MovedCharArray[$key])) {
                $MovedCharArray[$key] = $Chars[$MovedCharArray[$key]];
            }
            $NewString .= $MovedCharArray[$key];
        }
        if (bcmod($NewString, '97') == 1) {
            return true;
        }
    }
    return false;
}
// Check formatting of IBAN
function validateIbanFormatting(string $str): bool
{
    // Note: German IBAN definition allows for slack
    // Correct IBAN definition: DE[0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
    if (str_starts_with($str,'DE')) {
        $re = 'DE\s?[0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?';
        // Find all IBAN addresses
        if (preg_match_all('/' . $re . '/', $str, $m)) {
            return true;
        } else {
            return false;
        }
    } else {
        // International IBANs are validated in the validateIbanChecksum() function
        return true;
    }
}