<?php

require_once __DIR__ . "/required.php";

$shipmentinfo = [];

try {

    if (empty($_REQUEST["to_street"])) {
        throw new Exception("Please enter the delivery address.");
    }

    if (empty($_REQUEST["to_name"]) && empty($_REQUEST["to_company"])) {
        throw new Exception("Please enter the recipient's name and/or a company name.");
    }

    if (empty($_REQUEST["to_zip"]) && (empty($_REQUEST["to_city"]) || empty($_REQUEST["to_state"]))) {
        throw new Exception("Please enter the delivery ZIP code, or if you don't know, enter the city and state and we'll find the ZIP code for you.");
    }

    if (empty($_REQUEST["from_name"]) || empty($_REQUEST["from_street"])) {
        throw new Exception("Please enter your return address.");
    }

    if (empty($_REQUEST["from_zip"]) && (empty($_REQUEST["from_city"]) || empty($_REQUEST["from_state"]))) {
        throw new Exception("Please enter your ZIP code, or if you don't know, enter your city and state and we'll find the ZIP code for you.");
    }

    if (empty($_REQUEST["from_email"]) || !filter_var($_REQUEST["from_email"], FILTER_VALIDATE_EMAIL)) {
        throw new Exception("Please enter your email address. We use it to send you a receipt with your tracking number and other info. You won't get any spam emails, we promise.");
    }

    $shipmentinfo["from_address"] = \EasyPost\Address::create([
                "verify" => array("delivery"),
                "name" => $_REQUEST["from_name"],
                "street1" => $_REQUEST["from_street"],
                "street2" => $_REQUEST["from_street2"],
                "city" => $_REQUEST["from_city"],
                "state" => $_REQUEST["from_state"],
                "zip" => $_REQUEST["from_zip"],
                "email" => $_REQUEST["from_email"],
                "country" => "US"
    ]);

    $shipmentinfo["to_address"] = \EasyPost\Address::create([
                "verify" => array("delivery"),
                "name" => $_REQUEST["to_name"],
                "company" => $_REQUEST["to_company"],
                "street1" => $_REQUEST["to_street"],
                "street2" => $_REQUEST["to_street2"],
                "city" => $_REQUEST["to_city"],
                "state" => $_REQUEST["to_state"],
                "zip" => $_REQUEST["to_zip"],
                "country" => "US"
    ]);

    $weight = 3.5;

    if (!empty($_REQUEST["page_count"]) && is_numeric($_REQUEST["page_count"])) {
        // about 5 pages per ounce
        $weight = ($_REQUEST["page_count"] * 1 + 1) / 5;
    } else {
        throw new Exception("Enter the number of pages you're sending so we can estimate the weight for your postage.");
    }

    if ($weight > 3.5 && $_REQUEST["postagetype"] == "first") {
        throw new Exception("Too many pages to send as a First-Class letter. Use Priority Mail instead.");
    }
    if ($weight > 160) {
        // Don't allow over 10 pounds, seems like a good stopping point...
        throw new Exception("Wow, that's a lot of pages! You should mail that at a Post Office instead to make sure it's handled and weighed properly.");
    }
    if ($_REQUEST["page_count"] * 1 > 20
            && $_REQUEST["postagetype"] == "priority"
            && (empty($_REQUEST["label_only"]) || $_REQUEST["label_only"] != "label_only")
            && (empty($_REQUEST["flat_rate"]) || $_REQUEST["flat_rate"] != "flat_rate")) {
        throw new Exception("That probably won't fit in our DIY printable envelope. Select the \"Print Postage Only\" option and use your own (large) envelope instead.");
    }

    if (!empty($_REQUEST["flat_rate"]) && $_REQUEST["flat_rate"] == "flat_rate") {
        if (!empty($_REQUEST["no10_envelope"]) && $_REQUEST["no10_envelope"] == "no10_envelope") {
            throw new Exception("You can't use your own envelope with Priority Mail Flat Rate. Use a USPS-provided Flat Rate envelope instead.");
        }
        $shipmentinfo["parcel"] = \EasyPost\Parcel::create([
                    "predefined_package" => "FlatRateEnvelope",
                    "weight" => $weight
        ]);
    } else {
        $shipmentinfo["parcel"] = \EasyPost\Parcel::create([
                    "predefined_package" => "Letter",
                    "weight" => $weight
        ]);
    }


    if (empty($_SETTINGS["test"]) || $_SETTINGS["test"] != true) {
        $shipmentinfo["carrier_accounts"] = [$_SETTINGS["easypost_usps_account"]]; // USPS
    }

    if ($_REQUEST["postageservice"] == "certified") {
        $shipmentinfo["options"]["certified_mail"] = true;
    } else if ($_REQUEST["postageservice"] == "certified_receipt") {
        $shipmentinfo["options"]["certified_mail"] = true;
        $shipmentinfo["options"]["return_receipt"] = true;
    }

    if (!empty($_REQUEST["restricted_delivery"]) && $_REQUEST["restricted_delivery"] == "restricted_delivery") {
        if (!empty($shipmentinfo["options"]["certified_mail"]) && $shipmentinfo["options"]["certified_mail"] == true) {
            $shipmentinfo["options"]["delivery_confirmation"] = "SIGNATURE_RESTRICTED";
        } else {
            throw new Exception("Restricted Delivery is only available with Certified Mail.");
        }
    }

    if ($_REQUEST["postagetype"] == "priority") {
        $shipmentinfo["options"]["label_format"] = "PNG";
        $shipmentinfo["options"]["label_size"] = "4x6";
    } else {
        $shipmentinfo["options"]["label_format"] = "PNG";
        $shipmentinfo["options"]["label_size"] = "7x3";
    }


    if ($_REQUEST["postagetype"] == "first" && ((!empty($_REQUEST["flat_rate"]) && $_REQUEST["flat_rate"] == "flat_rate") || (!empty($_REQUEST["label_only"]) && $_REQUEST["label_only"] == "label_only"))) {
        throw new Exception("First-Class Mail can't be combined with the \"Print Postage Only\" or the \"Print Flat Rate Postage\" options.");
    }


    $mailing_date = date("c", strtotime("tomorrow"));
    if (!empty($_REQUEST["mailing_date"])) {
        if (!preg_match("/^20(2[3-9]|[3-4][0-9])-(0[1-9]|1[0-2])-([0-2][0-9]|3[0-1])$/", $_REQUEST["mailing_date"])) {
            throw new Exception("Invalid mailing date.");
        }
        if (strtotime($_REQUEST["mailing_date"]) < strtotime(date("Y-m-d"))) {
            throw new Exception("Mailing date cannot be in the past.");
        }
        if (strtotime($_REQUEST["mailing_date"]) > strtotime("now + 14 days")) {
            throw new Exception("Mailing date must be sooner than two weeks from now.");
        }
        $mailing_date = date("c", strtotime($_REQUEST["mailing_date"]));
    }

    $shipmentinfo["options"]["label_date"] = $mailing_date;

    $shipment = \EasyPost\Shipment::create($shipmentinfo);

    $selectedrate = [];
    for ($i = 0; $i < count($shipment->rates); $i++) {
        $rate = $shipment->rates[$i];

        $retail_rate = $rate->retail_rate ?? ($rate->list_rate ?? $rate->rate);
        if ($_REQUEST["postagetype"] == "priority" && $rate->service != "Priority") {
            continue;
        }
        if ($_REQUEST["postagetype"] == "first" && $rate->service != "First") {
            continue;
        }

        $selectedrate = [
            "id" => $rate->id,
            "cost" => $rate->rate,
            "price" => $retail_rate + 1.00
        ];
    }

    if (empty($selectedrate)) {
        throw new Exception("Unable to find price. Check your destination address and try again.");
    }

    $address = $shipment->to_address;
    $fromaddress = $shipment->from_address;

    header("Content-Type: application/json");

    exit(json_encode([
        "status" => "OK",
        "rate" => $selectedrate,
        "shipmentid" => $shipment->id,
        "address" => [
            "name" => $address->name ?? "",
            "company" => $address->company ?? "",
            "street1" => $address->street1 ?? "",
            "street2" => $address->street2 ?? "",
            "city" => $address->city ?? "",
            "state" => $address->state ?? "",
            "zip" => $address->zip ?? ""
        ],
        "fromaddress" => [
            "name" => $fromaddress->name ?? "",
            "street1" => $fromaddress->street1 ?? "",
            "street2" => $fromaddress->street2 ?? "",
            "city" => $fromaddress->city ?? "",
            "state" => $fromaddress->state ?? "",
            "zip" => $fromaddress->zip ?? "",
            "email" => $fromaddress->email ?? ""
        ]]
    ));
} catch (Exception $ex) {
    header("Content-Type: application/json");
    exit(json_encode(["status" => "ERROR", "message" => $ex->getMessage()]));
}