<?php

namespace Inforbank\Application\Helper;

use Exception;
use Inforbank\Application;
use Inforbank\Application\Helper\Rekeningen;

class Overboekingen
{
    public static $EIGENAAR = 1;
    public static $IBAN = 2;
    public static $BANK = 3;
    public static $BESTAAN = 4;
    public static $ZELFDE = 5;
    public static $GETAL = 6;
    public static $POSITIEF = 7;
    public static $SALDO = 8;
    public static $OMSCHRIJVING = 9;
    public static $SPAARREKENING = 10;

    public static function getErrorMessage($code)
    {
        switch ($code) {
            case Overboekingen::$EIGENAAR:
                $message = "U bent niet de eigenaar van de betalende rekening.";
                break;
            case Overboekingen::$IBAN:
                $message = "Het ontvangende rekeningnummer is ongeldig.";
                break;
            case Overboekingen::$BANK:
                $message = "U kunt alleen binnen de InforBank geld overmaken.";
                break;
            case Overboekingen::$BESTAAN:
                $message = "De 'naar' rekening bestaat niet.";
                break;
            case Overboekingen::$ZELFDE:
                $message = "De 'van' en 'naar' rekening mogen niet hetzelfde zijn.";
                break;
            case Overboekingen::$GETAL:
                $message = "Het bedrag moet een getal zijn met maximaal 9 cijfers voor en 2 achter de komma.";
                break;
            case Overboekingen::$POSITIEF:
                $message = "Het bedrag moet positief zijn.";
                break;
            case Overboekingen::$SALDO:
                $message = "Uw saldo is te laag voor deze betaling.";
                break;
            case Overboekingen::$OMSCHRIJVING:
                $message = "De omschrijving mag niet langer dan 40 tekens zijn.";
                break;
            case Overboekingen::$SPAARREKENING:
                $message = "Je kan geen geld overmaken van of naar een spaarrekening van een ander.";
                break;
            default:
                $message = "";
                break;
        }
        return $message;
    }

    public static function isValidFloat($bedrag)
    {
        $komma = 0;
        $decimalen = 0;
        $cijfers = 0;
        for ($i = 0; $i < strlen($bedrag); $i++) {
            $char = substr($bedrag, $i, 1);
            $ascii = ord($char);
            if ($char === "." || $char === ",") {
                $komma++;
                if ($komma > 1) {
                    //Twee komma's
                    return false;
                }
            } elseif (($ascii >= ord("0") && $ascii <= ord("9") || $char === "-")) {
                if ($komma >= 1) {
                    $decimalen++;
                    if ($decimalen > 2) {
                        //Meer dan twee cijfers achter de komma
                        return false;
                    }
                } else {
                    $cijfers++;
                    if ($cijfers > 9) {
                        //Te veel cijfers voor de komma
                        return false;
                    }
                }
            } else {
                //Ongeldig teken
                return false;
            }
        }
        return true;
    }

    private static function error($code)
    {
        throw new Exception(Overboekingen::getErrorMessage($code), $code);
    }

    /**
     * Maak een nieuwe overboeking aan
     * @param IBAN $van De rekening waar het bedrag vanaf wordt gehaald
     * @param IBAN $naar De rekening waar het bedrag bijkomt
     * @param double $bedrag Het bedrag
     * @param string $omschrijving De omschrijving van de overoeking
     * $param string $type Het type overboeking
     */
    public static function createOverboeking($van, $naar, $bedrag, $omschrijving, $type)
    {
        $vanRekening = Rekeningen::isEigenRekeningIBAN($van);
        if (!$vanRekening) {
            //error: rekening is niet van klant
            Overboekingen::error(Overboekingen::$EIGENAAR);
        }

        if (!IBAN::isValidIBAN($naar)) {
            //error: ongeldige iban
            throw new Exception("De IBAN van de ontvanger is ongeldig.", Overboekingen::$IBAN);
        } elseif (!(IBAN::getLand($naar) == "NL" && IBAN::getBank($naar) === "INFO")) {
            //error: andere bank
            Overboekingen::error(Overboekingen::$BANK);
        }
        $naarRekeningnr = IBAN::getRekeningNummer($naar);

        //Controleer of de rekening bestaat
        $db = Application::getContainer()->db;
        $naarRekeningen = $db->rekeningen->where("rekeningnr", $naarRekeningnr);
        if (count($naarRekeningen) !== 1) {
            //error: rekening bestaat niet
            Overboekingen::error(Overboekingen::$BESTAAN);
        }
        $naarRekening = $naarRekeningen[array("rekeningnr" => $naarRekeningnr)];
        if ($naarRekeningnr == $vanRekening['nr']) {
            //error: afzender is hetzelfde als ontvanger
            Overboekingen::error(Overboekingen::$ZELFDE);
        }

        if (!Rekeningen::isEigenRekeningnr($naarRekeningnr)
                && ((int)$naarRekening['typeid'] === Rekeningen::$SPAARREKENING
                    || (int)$vanRekening['typeid'] === Rekeningen::$SPAARREKENING)) {
            Overboekingen::error(Overboekingen::$SPAARREKENING);
        }

        if (!Overboekingen::isValidFloat($bedrag)) {
            Overboekingen::error(Overboekingen::$GETAL);
        }

        $bedragvalue = doubleval(str_replace(",", ".", $bedrag));

        if ($bedragvalue <= 0) {
            Overboekingen::error(Overboekingen::$POSITIEF);
        }

        if ($bedragvalue > $vanRekening['saldo']) {
            Overboekingen::error(Overboekingen::$SALDO);
        }
        if (strlen($omschrijving) > 40 && $type !== "id") {
            //error: te lange omschrijving
            Overboekingen::error(Overboekingen::$OMSCHRIJVING);
        }
        //Voeg transactie toe
        $db->transacties->insert([
            "van" => $vanRekening['nr'],
            "naar" => $naarRekeningnr,
            "bedrag" => $bedragvalue,
            "type" => $type,
            "omschrijving" => $omschrijving,
            "datum" => date("Y-m-d")
        ]);

        //Wijzig saldo
        $db->rekeningen->where("rekeningnr", $vanRekening['nr'])->update([
            "saldo" => ((double) $vanRekening['saldo'] - $bedragvalue)
        ]);
        $naarRekening->update([
            "saldo" => ((double) $naarRekening['saldo'] + $bedragvalue)
        ]);
        //Stuur bericht bij laag saldo
        if ($vanRekening['saldo'] - $bedragvalue < 20) {
            Berichten::newBericht(Application::getContainer()->auth->getUserID(), "Bank", "U heeft een laag saldo op uw rekening: " . IBAN::getIBAN($vanRekening['nr']) . ".<br/>Uw huidige saldo is " . money_format('%(#1n', $vanRekening['saldo'] - $bedragvalue) . ".");
        }
        //In de database worden de getallen met 10 cijfers voor de komma opgeslagen
        //Als het saldo te hoog wordt heb je een probleem
        if ($naarRekening['saldo'] + $bedragvalue > 9000000000) {
            Berichten::newBericht($naarRekening['klantid'], "Bank", "Uw saldo is te hoog!");
        }
    }
}
