<?php

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

require_once __DIR__ . "/../../lib/requiredpublic.php";

require_once __DIR__ . "/../../lib/Email.lib.php";

function errorBack(string $errormsg) {
    global $familyid;
    header("Location: ../?page=signup&error=" . htmlentities($errormsg));
    $database->delete("families", ["familyid" => $familyid]);
    die($errormsg);
}

$database->action(function($database) {
    global $SETTINGS;

    $database->insert("families", []);
    $familyid = $database->id();

    $dueusd = 0.0;

    $emails = [];

    try {

        $people = $_POST['people'];

        $requiredfields = [
            "firstname" => ".+",
            "lastname" => ".+",
            "address" => ".+",
            "zip" => "[0-9]{5}(-?[0-9]{4})?",
            "phone1" => "[0-9]{10}",
            "email" => "_EMAIL_",
            "shirt" => ["NO", "YS", "YM", "YL", "AS", "AM", "AL", "AX", "A2"],
            "sex" => ["M", "F"]
        ];

        if (count($people['ids']) == 0) {
            errorBack("You need to register at least one person.");
        }

        foreach ($people['ids'] as $pid) {
            // Clear these out
            $camperid = null;
            $adultid = null;
            $youthid = null;
            switch ($people["type"][$pid]) {
                case "camper":
                    $checkfields = array_merge($requiredfields, [
                        "parentname" => ".+",
                        "unit" => "[0-9]{3,4}",
                        "rank" => ["Tiger", "Wolf", "Bear", "Webelos", "Arrow of Light"]
                    ]);
                    break;
                case "adult":
                    $checkfields = array_merge($requiredfields, [
                        "position" => [
                            "None",
                            "Den Walker",
                            "Station Leader",
                            "Tot Lot",
                            "First Aid",
                            "Floater"
                        ]
                    ]);
                    break;
                case "youth":
                    $checkfields = array_merge($requiredfields, [
                        "position" => [
                            "None",
                            "Den Chief",
                            "Station",
                            "Tot Lot",
                            "Floater"
                        ]
                    ]);
                    break;
                default:
                    errorBack("Invalid person type.");
            }
            foreach ($checkfields as $name => $regex) {
                $validatefunction = function ($str) use ($regex) {
                    return preg_match("/$regex/", $str);
                };

                if (is_array($regex)) {
                    // Array of options
                    $validatefunction = function ($str) use ($regex) {
                        return in_array($str, $regex);
                    };
                } else if (strpos($regex, "_") === 0) {
                    // Special cases
                    switch ($regex) {
                        case "_EMAIL_":
                            $validatefunction = function ($str) {
                                return filter_var($str, FILTER_VALIDATE_EMAIL);
                            };
                            break;
                    }
                }

                // Validate
                if (!$validatefunction($people[$name][$pid])) {
                    errorBack("Please check your input and try again ($name).");
                }
            }


            $days = "";
            if (is_array($people["days"][$pid])) {
                $validdays = ["Tu", "We", "Th", "Fr"];
                $days = "";
                foreach ($people["days"][$pid] as $day) {
                    if (in_array($day, $validdays)) {
                        $days .= $day;
                    }
                }
            }

            switch ($people["type"][$pid]) {
                case "camper":
                    $dueusd += 50.0;
                    echo "\nAdding $50 to the total for a camper, dueusd is $dueusd\n";
                    $database->insert("campers", [
                        "parentname" => $people["parentname"][$pid],
                        "rank" => $people["rank"][$pid]
                    ]);
                    $camperid = $database->id();
                    break;
                case "adult":
                    $discount = 10.0 * (strlen($days) / 2);
                    $dueusd -= $discount;
                    echo "Subtracting $$discount from the total for an adult volunteer, dueusd is $dueusd\n";
                    // Add shirt cost
                    if ($people["shirt"][$pid] != "NO" && (strlen($days) / 2) < 4) {
                        echo "Adding $10 for a tshirt.\n";
                        $dueusd += 10.0;
                    }
                    $database->insert("adults", [
                        "position" => $people["position"][$pid],
                        "days" => $days
                    ]);
                    $adultid = $database->id();
                    break;
                case "youth":
                    if ($people["shirt"][$pid] != "NO" && (strlen($days) / 2) < 2) {
                        echo "Adding $10 for a tshirt.\n";
                        $dueusd += 10.0;
                    }
                    $database->insert("youth", [
                        "position" => $people["position"][$pid],
                        "days" => $days
                    ]);
                    $youthid = $database->id();
                    break;
            }


            $database->insert("people", [
                "familyid" => $familyid,
                "camperid" => $camperid,
                "adultid" => $adultid,
                "youthid" => $youthid,
                "firstname" => $people["firstname"][$pid],
                "lastname" => $people["lastname"][$pid],
                "address" => $people["address"][$pid],
                "zip" => $people["zip"][$pid],
                "phone1" => empty($people["phone1"][$pid]) ? "" : $people["phone1"][$pid],
                "phone2" => empty($people["phone2"][$pid]) ? "" : $people["phone2"][$pid],
                "email" => empty($people["email"][$pid]) ? "" : $people["email"][$pid],
                "unit" => $people["unit"][$pid],
                "shirt" => $people["shirt"][$pid],
                "sex" => $people["sex"][$pid]
            ]);

            if (!empty($people["email"][$pid])) {
                $emails[] = $people["email"][$pid];
            }
        }
    } catch (Exception $ex) {
        errorBack($ex->getMessage());
    }


    //
    // Payment
    //

    $campcoupons = (!empty($_POST['campcoupons']) && preg_match("/[0-9]+/", $_POST['campcoupons'])) ? $_POST['campcoupons'] * 1 : 0;

    if ($campcoupons < 0) {
        $campcoupons = 0;
    }

    $dueusd = max(0, $dueusd);

    $duecard = max(0, $dueusd - $campcoupons);

    echo "\nCost $dueusd total: $duecard to Stripe, $campcoupons as coupons\n";

    if ($dueusd != $_POST['totalcharge']) {
        errorBack("There was a discrepency between the total you saw and the total the server calculated.  The transaction has been cancelled and you were not charged.");
    }

    if ($duecard > 0) {
        try {
            \Stripe\Stripe::setApiKey($SETTINGS["stripe"]["seckey"]);

            $chargedata = [
                'amount' => $duecard * 100.0,
                'currency' => 'usd',
                'description' => 'Day Camp ' . date('Y'),
                'source' => $_POST['stripeToken']
            ];

            if (count($emails) > 0) {
                $chargedata['receipt_email'] = $emails[0];
            }

            $charge = \Stripe\Charge::create($chargedata);
        } catch (\Stripe\Error\Card $e) {
            $body = $e->getJsonBody();
            $err = $body['error'];
            errorBack("We couldn't process your card because it was declined.  Your card issuer or bank sent us this message: " . $err["message"] . "  That's all we know.");
        } catch (\Stripe\Error\RateLimit $e) {
            errorBack("We couldn't process your card because things are happening too fast.  Please try again in a minute.  Your card was not charged. (Error code: STRIPE_RATELIMIT)");
        } catch (\Stripe\Error\InvalidRequest $e) {
            errorBack("We couldn't process your card because of a technical issue.  Please try again later.  Your card was not charged. (Error code: STRIPE_INVREQ)");
        } catch (\Stripe\Error\Authentication $e) {
            errorBack("We can't connect to the card processor.  Please try again later.  Your card was not charged. (Error code: STRIPE_AUTH)");
        } catch (\Stripe\Error\ApiConnection $e) {
            errorBack("We can't connect to the card processor.  Please try again later.  Your card was not charged.  (Error code: STRIPE_NOAPI)");
        } catch (\Stripe\Error\Base $e) {
            errorBack("An unknown payment error occurred.  Please try again later.  Your card was not charged.");
        } catch (Exception $e) {
            errorBack("An unknown error occurred.  Please try again later.  Your card was not charged.");
        }
    }

    $database->insert("payments", [
        "familyid" => $familyid,
        "amount" => $dueusd,
        "amountpaid" => $duecard,
        "date" => date("Y-m-d H:i:s"),
        "type" => "Online"
    ]);

    header("Location: ../?page=thanks");
    return true;
});
