using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Sockeye.Models;
using Sockeye.Util;

namespace Sockeye.Biz
{


    /// <summary>
    /// Process vendor notifications
    /// Turn vendordata into fully filled out purchase
    /// attempt to match to existing customer or create one if necessary
    ///
    ///  A Separate job will make licenses from the new purchases where feasible
    ///
    /// </summary>
    internal static class SockBotProcessVendorNotifications
    {
        private static ILogger log = Sockeye.Util.ApplicationLogging.CreateLogger("SockBotProcessVendorNotifications");
        private static DateTime lastSweep = DateTime.MinValue;
#if (DEBUG)
        private static TimeSpan PROCESS_EVERY_INTERVAL = new TimeSpan(0, 0, 30);//every 30 seconds during development
#else
        private static TimeSpan PROCESS_EVERY_INTERVAL = new TimeSpan(0, 5, 10);//every 5 minutes 
#endif
        ////////////////////////////////////////////////////////////////////////////////////////////////
        // DoSweep
        //
        public static async Task DoWorkAsync()
        {
            //This will get triggered roughly every minute, but we don't want to check that frequently
            if (DateTime.UtcNow - lastSweep < PROCESS_EVERY_INTERVAL)
                return;

            if (ServerBootConfig.MIGRATING) return;//don't do this during migration (migration is one time only so can remove after up and running)

            log.LogDebug("Process vendor notifications starting");
            await ProcessVendorNotificationDataIntoPurchases();

            lastSweep = DateTime.UtcNow;
        }

        private static async Task ProcessVendorNotificationDataIntoPurchases()
        {
            using (AyContext ct = Sockeye.Util.ServiceProviderProvider.DBContext)
            {

                //get a list of all actionable vendor notifications
                var vnList = await ct.VendorNotification
                                 .Where(z => z.Processed == null)
                                 .OrderBy(z => z.Id)
                                 .ToListAsync();

                try
                {
                    foreach (var vn in vnList)
                    {
                        log.LogDebug($"Processing vendor notification {vn.Id}-{vn.Created}");
                        if (string.IsNullOrWhiteSpace(vn.VendorData))
                        {
                            var err = $"VendorNotification record {vn.Id}-{vn.Created} has no vendor data";
                            await NotifyEventHelper.AddOpsProblemEvent("SockBotProcessVendorNotifications: " + err);
                            log.LogError(err);
                            continue;
                        }
                        //Parse json vendordata
                        if (await ParseVendorNotificationData(vn, ct, log))
                        {
                            //success, save vendornotification as processed 
                            vn.Processed = DateTime.UtcNow;
                            await ct.SaveChangesAsync();
                        }

                    }
                }
                catch (Exception ex)
                {
                    var err = "SockBotProcessVendorNotifications error running job";
                    //serious issue requires immediate notification
                    await NotifyEventHelper.AddOpsProblemEvent(err, ex);
                    log.LogError(ex, err);
                }

            }
        }


        internal static async Task<bool> ParseVendorNotificationData(VendorNotification vn, AyContext ct, ILogger log)
        {

            try
            {
                var jData = JObject.Parse(vn.VendorData);

                //It's a test purchase, no need to process it any further...or is there??
                bool IsTestOrder = false;
                if (jData["order_notification"]["purchase"]["is_test"] != null && jData["order_notification"]["purchase"]["is_test"].Value<bool>() == true)
                    IsTestOrder = true;

                //fundamentally validate the object is a purchase notification
                if (jData["order_notification"]["purchase"]["purchase_id"] == null)
                {
                    //this is not the expected format data, stop processing and alert:
                    throw new System.FormatException($"Vendor data unexpected format:{vn.VendorData}");
                }
                //parse purchases collection needed up front as it potentially contains Customer record relevant data
                var jaPurchaseList = (JArray)jData["order_notification"]["purchase"]["purchase_item"];
                string RavenDBId = string.Empty;
                foreach (JObject jPurchase in jaPurchaseList)
                {
                    /////DATABASE ID if available used to matchup
                    //Capture raven database id if present
                    if (jPurchase["additional_information"] != null)
                    {
                        var jaAdditionalItems = (JArray)jPurchase["additional_information"];
                        foreach (JObject jAdditionalItem in jaAdditionalItems)
                        {
                            if (jAdditionalItem["additional_id"] != null && jAdditionalItem["additional_id"].Value<string>() == "DATABASEID")
                            {
                                RavenDBId = jAdditionalItem["additional_value"].Value<string>();
                                break;
                            }
                        }
                    }
                }

                ///////////////////////////////////////////////////////////////////////////////////////////      
                #region CUSTOMER MAKE OR LOCATED
                ///////////////////////////////////////////////////////////////////////////////////////////      
                //Note: always use reg name not customer name as it may vary between the two and regname is the one we care about          
                var jCustomerName = jData["order_notification"]["purchase"]["customer_data"]["reg_name"].Value<string>() ?? throw new System.FormatException($"Vendor data empty reg_name:{vn.VendorData}");
                if (jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["email"] == null)//we can't process orders with no email at all hard no
                    throw new System.FormatException($"Vendor data empty email:{vn.VendorData}");
                var jCustomerEmail = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["email"].Value<string>();
                var jCustomerAccountNumber = jData["order_notification"]["purchase"]["customer_data"]["shopper_id"].Value<string>();//appears to be mycommerce customer id number hopefully static between orders

                var customerBiz = CustomerBiz.GetBiz(ct);


                //attempt to match to existing customer
                //databaseID for raven is best match,account number is next most ideal match, , then name but could be multiple in sockeye from rockfish sites so name will start the same, finally email if nothing else
                Customer customer = null;

                //First best match is RavenDBID
                if (!string.IsNullOrWhiteSpace(RavenDBId))
                    customer = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.DbId == RavenDBId);

                //if not found then try match in order of best matching
                if (customer == null)
                    customer = await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.AccountNumber == jCustomerAccountNumber)
                                        ?? await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.Name.StartsWith(jCustomerName))
                                        ?? await ct.Customer.AsNoTracking().FirstOrDefaultAsync(z => z.EmailAddress == jCustomerEmail);

                //still no match, consider it a new customer
                if (customer == null)
                {
                    //New customer
                    customer = new Customer();
                    customer.Name = jCustomerName;
                    customer.EmailAddress = jCustomerEmail;
                    customer.AccountNumber = jCustomerAccountNumber;
                    UpdateCustomerFromVendorData(jData, customer);
                    customer = await customerBiz.CreateAsync(customer);
                    if (customer == null)
                        throw new System.ApplicationException($"Error creating new Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}");
                }
                else
                {
                    //existing customer
                    //here there could be several potential issues:
                    //name differs because it was a separate site in rockfish, it's not cool to change the name
                    //email differs, this can happen and is ok
                    //account number differs if was empty then it's ok.  If it wasn't empty and it differs this is unfortunately normal as users may re-buy again with new account or buy an addon with a new account
                    //so the vendor account nubmer should just be the most recent for finding them purposes I guess
                    //  
                    if (customer.EmailAddress != jCustomerEmail)
                        customer.EmailAddress = jCustomerEmail;//assume it was empty or has been recently updated                    

                    if (customer.AccountNumber != jCustomerAccountNumber)
                        customer.AccountNumber = jCustomerAccountNumber;//see above


                    //refresh
                    UpdateCustomerFromVendorData(jData, customer);
                    customer = await customerBiz.PutAsync(customer);
                    if (customer == null)
                        throw new System.ApplicationException($"Error updating existing Customer: {customerBiz.GetErrorsAsString()} vendor data :{vn.VendorData}");
                }
                ///////////////////////////////////////////////////////////////////////////////////////////      
                #endregion customer make or locate

                ///////////////////////////////////////////////////////////////////////////////////////////      
                #region MAKE PURCHASE RECORD                
                ///////////////////////////////////////////////////////////////////////////////////////////      

                var salesOrderNumber = jData["order_notification"]["purchase"]["purchase_id"].Value<string>();
                if (IsTestOrder)
                    salesOrderNumber = "test-order-" + salesOrderNumber;
#if (DEBUG)
                salesOrderNumber += "-debug-test";
#endif

                //https://www.newtonsoft.com/json/help/html/DatesInJSON.htm
                var purchaseDate = jData["order_notification"]["purchase"]["purchase_date"].Value<DateTime>();

                if (await ct.Purchase.AnyAsync(z => z.SalesOrderNumber == salesOrderNumber))
                    throw new System.ApplicationException($"Sales order already exists: {salesOrderNumber} will not be processed");

                //iterate purchase items array                
                foreach (JObject jPurchase in jaPurchaseList)
                {
                    Purchase p = new Purchase();
                    p.PurchaseDate = purchaseDate;
                    p.CustomerId = customer.Id;
                    p.RegTo = jCustomerName;
                    p.VendorId = vn.VendorId;
                    p.SalesOrderNumber = salesOrderNumber;
                    var SalesItemProductVendorCode = jPurchase["product_id"].Value<string>();
                    var product = await ct.Product.AsNoTracking().FirstOrDefaultAsync(z => z.VendorCode == SalesItemProductVendorCode) ?? throw new System.ArgumentOutOfRangeException($"Vendor product code:{SalesItemProductVendorCode} was not found in Sockeye Products, record not processed");
                    p.ProductId = product.Id;
                    p.PGroup = product.PGroup;
                    if (jPurchase["accounting"] != null)
                    {
                        p.Currency = jPurchase["accounting"]["currency"].Value<string>();
                        p.ProductNet = jPurchase["accounting"]["product_net"].Value<decimal>();
                        p.Discount = jPurchase["accounting"]["discount"].Value<decimal>();
                        p.VendorFee = jPurchase["accounting"]["margin_net"].Value<decimal>();
                        p.Revenue = jPurchase["accounting"]["your_revenue"].Value<decimal>();
                    }

                    if (!string.IsNullOrWhiteSpace(RavenDBId))
                        p.DbId = RavenDBId;

                    if (jPurchase["promotion_coupon"] != null)
                        p.CouponCode = jPurchase["promotion_coupon"].Value<string>();

                    if (jPurchase["promotion"] != null)
                        p.CouponCode += $" {jPurchase["promotion"].Value<string>()}";

                    p.Quantity = jPurchase["quantity"].Value<int>();
                    p.VendorNotificationId = vn.Id;

                    //it's a subscription?
                    if (jPurchase["subscription"] != null && jPurchase["subscription"]["expiration_date"] != null)
                    {
                        p.ExpireDate = jPurchase["subscription"]["expiration_date"].Value<DateTime>();
                    }

                    PurchaseBiz pbiz = PurchaseBiz.GetBiz(ct);
                    p = await pbiz.CreateAsync(p);
                    if (p == null)
                    {
                        //did not save, throw an error
                        throw new System.ApplicationException($"Error creating purchase: {pbiz.GetErrorsAsString()} for product item: {SalesItemProductVendorCode} vendor data :{vn.VendorData}");
                    }
                }

                ///////////////////////////////////////////////////////////////////////////////////////////      
                #endregion make purchase record
            }
            catch (Exception ex)
            {
                var err = $"ParseVendorNotificationData: VendorNotification record {vn.Id}-{vn.Created} triggered exception, see log";
                await NotifyEventHelper.AddOpsProblemEvent(err);//notify, this is serious
                log.LogError(ex, err);
                return false;
            }
            return true; //successfully processed so vendor notification should be set to processed by caller
        }

        private static void UpdateCustomerFromVendorData(JObject jData, Customer c)
        {
            c.Active = true;//if they just made a purchase they are active even if they weren't before
            c.DoNotContact = false;//if they just made a purchase they are contactable even if they weren't before
            c.Address = c.PostAddress = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["street1"].Value<string>();
            c.City = c.PostCity = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["city"].Value<string>();

            //State doesn't always exist in mycommerce notifications
            if (jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["state"] != null)
                c.Region = c.PostRegion = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["state"].Value<string>();
            c.Country = c.PostCountry = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["country"].Value<string>();
            c.PostCode = c.AddressPostal = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["address"]["postal_code"].Value<string>();
            var firstName = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["first_name"].Value<string>() ?? "FirstNameEmpty";
            var lastName = jData["order_notification"]["purchase"]["customer_data"]["delivery_contact"]["last_name"].Value<string>() ?? "LastNameEmpty";
            var language = jData["order_notification"]["purchase"]["customer_data"]["language"].Value<string>() ?? "LanguageEmpty";
            if (string.IsNullOrWhiteSpace(c.Notes))
                c.Notes = string.Empty;
            if (!c.Notes.Contains(lastName))
            {
                if (c.Notes.Length > 0 && !c.Notes.EndsWith('\n'))
                    c.Notes += "\n";
                c.Notes += $"Purchase contact:{firstName} {lastName}, language: {language}\n";
            }

        }


        #region SAMPLE VENDOR PURCHASE NOTIFICATIONS
        /*


/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////// V7 MULTIPLE PRODUCTS IN ONE ORDER/////////////////////////////

{
  "creation_date": "2023-01-22T23:21:49Z",
  "id": 357678128,
  "order_notification": {
    "purchase": {
      "customer_data": {
        "billing_contact": {
          "address": {
            "city": "Courtenay",
            "country": "Canada",
            "country_id": "CA",
            "postal_code": "V9J9T6",
            "state": "British Columbia",
            "state_id": "BC",
            "street1": "05-3610 Christie Parkway"
          },
          "company": "GZTestCo",
          "email": "gzmailadmin@gmail.com",
          "first_name": "Test",
          "last_name": "Testerson"
        },
        "customer_payment_data": {
          "currency": "USD",
          "payment_method": "Other"
        },
        "delivery_contact": {
          "address": {
            "city": "Courtenay",
            "country": "Canada",
            "country_id": "CA",
            "postal_code": "V9J9T6",
            "state": "British Columbia",
            "state_id": "BC",
            "street1": "05-3610 Christie Parkway"
          },
          "company": "GZTestCo",
          "email": "gzmailadmin@gmail.com",
          "first_name": "Test",
          "last_name": "Testerson"
        },
        "language": "English",
        "language_iso": "en",
        "reg_name": "GZTestCo",
        "shopper_id": "65860321",
        "subscribe_newsletter": false,
        "user_id": "gzmailadmin@gmail.com-38"
      },
      "is_test": true,
      "payment_complete_date": "2023-01-22T23:21:48Z",
      "payment_status": "testpaymentarrived",
      "payment_status_id": "TCA",
      "purchase_date": "2023-01-22T23:21:47Z",
      "purchase_id": 843671213,
      "purchase_item": [
        {
          "additional_information": [
            {
              "additional_id": "ADDITIONAL1",
              "additional_value": "YES"
            },
            {
              "additional_id": "ADDITIONAL2",
              "additional_value": "YES"
            },
            {
              "additional_id": "ADDITIONAL3",
              "additional_value": "YES"
            }
          ],
          "currency": "USD",
          "delivery_type": "Electronically",
          "discount": 0.0,
          "extended_download_price": 0.0,
          "manual_order_price": 0.0,
          "notification_no": 0,
          "product_id": 300740317,
          "product_name": "Up to 5 AyaNova schedulable resource 1 year subscription license",
          "product_single_price": 695.0,
          "purchase_item_key": [],
          "quantity": 1,
          "running_no": 1,
          "shipping_price": 0.0,
          "shipping_vat_pct": 0.0,
          "subscription": {
            "expiration_date": "2024-01-22T23:21:48Z",
            "id": "843671213-1",
            "interval": "Yearly without end",
            "renewal_discount_count": "",
            "renewal_discount_start": "",
            "renewal_type": "auto",
            "retention_discount_count": "",
            "retention_discount_percent": "",
            "start_date": "2023-01-23T00:00:00",
            "status": "ToProcess",
            "status_id": "TOP"
          },
          "vat_pct": 12.0
        },
        {
          "additional_information": [
            {
              "additional_id": "ADDITIONAL1",
              "additional_value": "YES"
            },
            {
              "additional_id": "ADDITIONAL2",
              "additional_value": "YES"
            },
            {
              "additional_id": "ADDITIONAL3",
              "additional_value": "YES"
            }
          ],
          "currency": "USD",
          "delivery_type": "Electronically",
          "discount": 0.0,
          "extended_download_price": 0.0,
          "manual_order_price": 0.0,
          "notification_no": 0,
          "product_id": 300740314,
          "product_name": "optional add-on AyaNova RI (responsive interface) 1 year subscription license",
          "product_single_price": 199.0,
          "purchase_item_key": [],
          "quantity": 1,
          "running_no": 2,
          "shipping_price": 0.0,
          "shipping_vat_pct": 0.0,
          "subscription": {
            "expiration_date": "2024-01-22T23:21:48Z",
            "id": "843671213-2",
            "interval": "Yearly without end",
            "renewal_discount_count": "",
            "renewal_discount_start": "",
            "renewal_type": "auto",
            "retention_discount_count": "",
            "retention_discount_percent": "",
            "start_date": "2023-01-23T00:00:00",
            "status": "ToProcess",
            "status_id": "TOP"
          },
          "vat_pct": 12.0
        },
        {
          "additional_information": [
            {
              "additional_id": "ADDITIONAL1",
              "additional_value": "YES"
            }
          ],
          "currency": "USD",
          "delivery_type": "Electronically",
          "discount": 0.0,
          "extended_download_price": 0.0,
          "manual_order_price": 0.0,
          "notification_no": 0,
          "product_id": 300740321,
          "product_name": "optional add-on AyaNova WBI (web browser interface) 1 year subscription license",
          "product_single_price": 99.0,
          "purchase_item_key": [],
          "quantity": 1,
          "running_no": 3,
          "shipping_price": 0.0,
          "shipping_vat_pct": 0.0,
          "subscription": {
            "expiration_date": "2024-01-22T23:21:48Z",
            "id": "843671213-3",
            "interval": "Yearly without end",
            "renewal_discount_count": "",
            "renewal_discount_start": "",
            "renewal_type": "auto",
            "retention_discount_count": "",
            "retention_discount_percent": "",
            "start_date": "2023-01-23T00:00:00",
            "status": "ToProcess",
            "status_id": "TOP"
          },
          "vat_pct": 12.0
        },
        {
          "additional_information": [
            {
              "additional_id": "ADDITIONAL1",
              "additional_value": "YES"
            }
          ],
          "currency": "USD",
          "delivery_type": "Electronically",
          "discount": 0.0,
          "extended_download_price": 0.0,
          "manual_order_price": 0.0,
          "notification_no": 0,
          "product_id": 300740322,
          "product_name": "optional add-on AyaNova MBI (minimal browser interface) 1 year subscription license",
          "product_single_price": 99.0,
          "purchase_item_key": [],
          "quantity": 1,
          "running_no": 4,
          "shipping_price": 0.0,
          "shipping_vat_pct": 0.0,
          "subscription": {
            "expiration_date": "2024-01-22T23:21:48Z",
            "id": "843671213-4",
            "interval": "Yearly without end",
            "renewal_discount_count": "",
            "renewal_discount_start": "",
            "renewal_type": "auto",
            "retention_discount_count": "",
            "retention_discount_percent": "",
            "start_date": "2023-01-23T00:00:00",
            "status": "ToProcess",
            "status_id": "TOP"
          },
          "vat_pct": 12.0
        },
        {
          "additional_information": [
            {
              "additional_id": "ADDITIONAL1",
              "additional_value": "YES"
            }
          ],
          "currency": "USD",
          "delivery_type": "Electronically",
          "discount": 0.0,
          "extended_download_price": 0.0,
          "manual_order_price": 0.0,
          "notification_no": 0,
          "product_id": 300740323,
          "product_name": "optional add-on AyaNova QBI(QuickBooks interface) 1 year subscription license",
          "product_single_price": 99.0,
          "purchase_item_key": [],
          "quantity": 1,
          "running_no": 5,
          "shipping_price": 0.0,
          "shipping_vat_pct": 0.0,
          "subscription": {
            "expiration_date": "2024-01-22T23:21:48Z",
            "id": "843671213-5",
            "interval": "Yearly without end",
            "renewal_discount_count": "",
            "renewal_discount_start": "",
            "renewal_type": "auto",
            "retention_discount_count": "",
            "retention_discount_percent": "",
            "start_date": "2023-01-23T00:00:00",
            "status": "ToProcess",
            "status_id": "TOP"
          },
          "vat_pct": 12.0
        }
      ],
      "purchase_origin": "online"
    }
  }
}



        /////////////////////////////////////////////////////////////////////////////////////////////////////
        //////////////////////v7 export to xls add on/////////////////////////////
         {
"creation_date": "2023-01-20T00:18:33Z",
"id": 357520816,
"order_notification": {
"purchase": {
  "customer_data": {
    "billing_contact": {
      "address": {
        "city": "Cambridge",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "N1T 1J3",
        "state": "Ontario",
        "state_id": "ON",
        "street1": "181 Shearson Crescent"
      },
      "company": "Cambridge Elevating Inc",
      "email": "richard.wright@cambridgeelevating.com",
      "first_name": "Richard",
      "last_name": "Wright"
    },
    "customer_payment_data": {
      "currency": "USD",
      "payment_method": "MasterCard"
    },
    "delivery_contact": {
      "address": {
        "city": "Cambridge",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "N1T 1J3",
        "state": "Ontario",
        "state_id": "ON",
        "street1": "181 Shearson Crescent"
      },
      "company": "Cambridge Elevating Inc",
      "email": "richard.wright@cambridgeelevating.com",
      "first_name": "Richard",
      "last_name": "Wright"
    },
    "language": "English",
    "language_iso": "en",
    "reg_name": "Cambridge Elevating Inc",
    "shopper_id": "62545677",
    "subscribe_newsletter": false,
    "user_id": "richard.wright@cambridgeelevating.com-5"
  },
  "is_test": false,
  "payment_complete_date": "2023-01-20T00:18:33Z",
  "payment_status": "complete",
  "payment_status_id": "PCA",
  "purchase_date": "2023-01-20T00:18:31Z",
  "purchase_id": 843101393,
  "purchase_item": [
    {
      "accounting": {
        "currency": "USD",
        "product_net": 6.65,
        "discount": 0.0,
        "product_vat": 0.86,
        "shipping": 0.0,
        "shipping_vat": 0.0,
        "eu_vat": -0.86,
        "margin_net": -2.5,
        "your_revenue": 4.15
      },
      "additional_information": [
        {
          "additional_id": "ADDITIONAL1",
          "additional_value": "YES"
        }
      ],
      "currency": "USD",
      "delivery_type": "Electronically",
      "discount": 0.0,
      "extended_download_price": 0.0,
      "manual_order_price": 0.0,
      "notification_no": 7953,
      "product_id": 300740327,
      "product_name": "optional add-on plug-in Export to XLS 1 year subscription license",
      "product_single_price": 6.65,
      "purchase_item_key": [],
      "quantity": 1,
      "running_no": 1,
      "shipping_price": 0.0,
      "shipping_vat_pct": 0.0,
      "subscription": {
        "expiration_date": "2024-01-20T18:36:22Z",
        "id": "771160083-3",
        "interval": "Yearly without end",
        "original_notification_no": "7779",
        "original_purchase_id": "771160083",
        "original_running_no": "3",
        "renewal_discount_count": "",
        "renewal_discount_start": "",
        "renewal_type": "auto",
        "retention_discount_count": "",
        "retention_discount_percent": "",
        "start_date": "2022-01-20T00:00:00",
        "status": "ToProcess",
        "status_id": "TOP"
      },
      "vat_pct": 13.0
    }
  ],
  "purchase_origin": "Subscription",
  "sequential_invoice_no": "e5-DE-2023-00000163106"
}
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// V7 Scheduleable user //////////////////////

{
"creation_date": "2023-01-20T00:18:32Z",
"id": 357520809,
"order_notification": {
"purchase": {
  "customer_data": {
    "billing_contact": {
      "address": {
        "city": "Cambridge",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "N1T 1J3",
        "state": "Ontario",
        "state_id": "ON",
        "street1": "181 Shearson Crescent"
      },
      "company": "Cambridge Elevating Inc",
      "email": "richard.wright@cambridgeelevating.com",
      "first_name": "Richard",
      "last_name": "Wright"
    },
    "customer_payment_data": {
      "currency": "USD",
      "payment_method": "MasterCard"
    },
    "delivery_contact": {
      "address": {
        "city": "Cambridge",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "N1T 1J3",
        "state": "Ontario",
        "state_id": "ON",
        "street1": "181 Shearson Crescent"
      },
      "company": "Cambridge Elevating Inc",
      "email": "richard.wright@cambridgeelevating.com",
      "first_name": "Richard",
      "last_name": "Wright"
    },
    "language": "English",
    "language_iso": "en",
    "reg_name": "Cambridge Elevating Inc",
    "shopper_id": "62545677",
    "subscribe_newsletter": false,
    "user_id": "richard.wright@cambridgeelevating.com-5"
  },
  "is_test": false,
  "payment_complete_date": "2023-01-20T00:18:32Z",
  "payment_status": "complete",
  "payment_status_id": "PCA",
  "purchase_date": "2023-01-20T00:18:31Z",
  "purchase_id": 843101383,
  "purchase_item": [
    {
      "accounting": {
        "currency": "USD",
        "product_net": 577.5,
        "discount": 0.0,
        "product_vat": 75.08,
        "shipping": 0.0,
        "shipping_vat": 0.0,
        "eu_vat": -75.08,
        "margin_net": -29.05,
        "your_revenue": 548.45
      },
      "additional_information": [
        {
          "additional_id": "ADDITIONAL1",
          "additional_value": "YES"
        },
        {
          "additional_id": "ADDITIONAL2",
          "additional_value": "YES"
        },
        {
          "additional_id": "ADDITIONAL3",
          "additional_value": "YES"
        }
      ],
      "currency": "USD",
      "delivery_type": "Electronically",
      "discount": 0.0,
      "extended_download_price": 0.0,
      "manual_order_price": 0.0,
      "notification_no": 7952,
      "product_id": 300807973,
      "product_name": "Up to 15 AyaNova schedulable resource 1 year subscription license",
      "product_single_price": 577.5,
      "purchase_item_key": [],
      "quantity": 1,
      "running_no": 1,
      "shipping_price": 0.0,
      "shipping_vat_pct": 0.0,
      "subscription": {
        "expiration_date": "2024-01-20T18:36:22Z",
        "id": "771160083-1",
        "interval": "Yearly without end",
        "original_notification_no": "7777",
        "original_purchase_id": "771160083",
        "original_running_no": "1",
        "renewal_discount_count": "",
        "renewal_discount_start": "",
        "renewal_type": "auto",
        "retention_discount_count": "",
        "retention_discount_percent": "",
        "start_date": "2022-01-20T00:00:00",
        "status": "ToProcess",
        "status_id": "TOP"
      },
      "vat_pct": 13.0
    }
  ],
  "purchase_origin": "Subscription",
  "sequential_invoice_no": "e5-DE-2023-00000163105"
}
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////  NOT A LICENSE PRODUCT - CUSTOMIZATION SERVICES FOR REPORT TEMPLATE 

{
"creation_date": "2023-01-18T15:45:50Z",
"id": 357446088,
"order_notification": {
"purchase": {
  "customer_data": {
    "billing_contact": {
      "address": {
        "city": "Brunswick",
        "country": "USA",
        "country_id": "US",
        "postal_code": "38014",
        "state": "Tennessee",
        "state_id": "TN",
        "street1": "PO Box 374"
      },
      "company": "Tri-Star Medical Technologies LLC",
      "email": "stan@tri-starmedical.com",
      "first_name": "Stan",
      "last_name": "Hilton"
    },
    "customer_payment_data": {
      "currency": "USD",
      "payment_method": "Visa"
    },
    "delivery_contact": {
      "address": {
        "city": "Brunswick",
        "country": "USA",
        "country_id": "US",
        "postal_code": "38014",
        "state": "Tennessee",
        "state_id": "TN",
        "street1": "PO Box 374"
      },
      "company": "Tri-Star Medical Technologies LLC",
      "email": "stan@tri-starmedical.com",
      "first_name": "Stan",
      "last_name": "Hilton"
    },
    "language": "English",
    "language_iso": "en",
    "reg_name": "Tri-Star Medical Technologies LLC",
    "shopper_id": "65821033",
    "subscribe_newsletter": false,
    "user_id": "stan@tri-starmedical.com-1"
  },
  "is_test": false,
  "payment_complete_date": "2023-01-18T15:45:49Z",
  "payment_status": "complete",
  "payment_status_id": "PCA",
  "purchase_date": "2023-01-18T15:45:48Z",
  "purchase_id": 842819563,
  "purchase_item": [
    {
      "accounting": {
        "currency": "USD",
        "product_net": 50.0,
        "discount": 0.0,
        "product_vat": 4.63,
        "shipping": 0.0,
        "shipping_vat": 0.0,
        "eu_vat": -4.63,
        "margin_net": -5.14,
        "your_revenue": 44.86
      },
      "additional_information": [],
      "currency": "USD",
      "delivery_type": "Electronically",
      "discount": 0.0,
      "extended_download_price": 0.0,
      "manual_order_price": 0.0,
      "notification_no": 7945,
      "product_id": 300525428,
      "product_name": "AyaNova customization services",
      "product_single_price": 50.0,
      "purchase_item_key": [],
      "quantity": 1,
      "running_no": 1,
      "shipping_price": 0.0,
      "shipping_vat_pct": 0.0,
      "vat_pct": 9.25
    }
  ],
  "purchase_origin": "online",
  "sequential_invoice_no": "e5-US-2023-00000083100"
}
}
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////  TEST PURCHASE USING SPECIAL TEST CREDIT CARD NUMBER PROVIDED BY MYCOMMERCE  
{
"creation_date": "2023-01-18T04:24:28Z",
"id": 357424814,
"order_notification": {
"purchase": {
  "customer_data": {
    "billing_contact": {
      "address": {
        "city": "Courtenay",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "V9J9T6",
        "state": "British Columbia",
        "state_id": "BC",
        "street1": "05-3610 Christie Parkway"
      },
      "company": "GZTestCo",
      "email": "gzmailadmin@gmail.com",
      "first_name": "Test",
      "last_name": "Testerson"
    },
    "customer_payment_data": {
      "currency": "USD",
      "payment_method": "Other"
    },
    "delivery_contact": {
      "address": {
        "city": "Courtenay",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "V9J9T6",
        "state": "British Columbia",
        "state_id": "BC",
        "street1": "05-3610 Christie Parkway"
      },
      "company": "GZTestCo",
      "email": "gzmailadmin@gmail.com",
      "first_name": "Test",
      "last_name": "Testerson"
    },
    "language": "English",
    "language_iso": "en",
    "reg_name": "GZTestCo",
    "shopper_id": "65817245",
    "subscribe_newsletter": false,
    "user_id": "gzmailadmin@gmail.com-36"
  },
  "is_test": true,
  "payment_complete_date": "2023-01-18T04:24:28Z",
  "payment_status": "testpaymentarrived",
  "payment_status_id": "TCA",
  "purchase_date": "2023-01-18T04:24:28Z",
  "purchase_id": 842769483,
  "purchase_item": [
    {
      "additional_information": [],
      "currency": "USD",
      "delivery_type": "Electronically",
      "discount": 0.0,
      "extended_download_price": 0.0,
      "manual_order_price": 0.0,
      "notification_no": 0,
      "product_id": 300525428,
      "product_name": "AyaNova customization services",
      "product_single_price": 50.0,
      "purchase_item_key": [],
      "quantity": 1,
      "running_no": 1,
      "shipping_price": 0.0,
      "shipping_vat_pct": 0.0,
      "vat_pct": 12.0
    }
  ],
  "purchase_origin": "online"
}
}
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// RAVEN PERPETUAL

{
"creation_date": "2023-01-14T06:17:59Z",
"id": 357214426,
"order_notification": {
"purchase": {
  "customer_data": {
    "billing_contact": {
      "address": {
        "city": "Frankfort",
        "country": "USA",
        "country_id": "US",
        "postal_code": "46041",
        "state": "Indiana",
        "state_id": "IN",
        "street1": "47 N Jackson St."
      },
      "company": "ACCS",
      "email": "internet@accs.net",
      "first_name": "Marcus",
      "last_name": "Hodges"
    },
    "customer_payment_data": {
      "currency": "USD",
      "payment_method": "Visa"
    },
    "delivery_contact": {
      "address": {
        "city": "Frankfort",
        "country": "USA",
        "country_id": "US",
        "postal_code": "46041",
        "state": "Indiana",
        "state_id": "IN",
        "street1": "47 N Jackson St."
      },
      "company": "ACCS",
      "email": "internet@accs.net",
      "first_name": "Marcus",
      "last_name": "Hodges"
    },
    "language": "English",
    "language_iso": "en",
    "reg_name": "ACCS",
    "shopper_id": "65783365",
    "subscribe_newsletter": false,
    "user_id": "internet@accs.net"
  },
  "is_test": false,
  "payment_complete_date": "2023-01-14T06:17:59Z",
  "payment_status": "complete",
  "payment_status_id": "PCA",
  "purchase_date": "2023-01-14T06:17:58Z",
  "purchase_id": 841935113,
  "purchase_item": [
    {
      "accounting": {
        "currency": "USD",
        "product_net": 72.0,
        "discount": 0.0,
        "product_vat": 5.04,
        "shipping": 0.0,
        "shipping_vat": 0.0,
        "eu_vat": -5.04,
        "margin_net": -6.03,
        "your_revenue": 65.97
      },
      "additional_information": [
        {
          "additional_id": "AGREENOREFUNDS",
          "additional_value": "YES"
        },
        {
          "additional_id": "AGREEPAYMETHODVALIDCANCEL",
          "additional_value": "YES"
        },
        {
          "additional_id": "AGREEEXPIRESIFNOTPAID",
          "additional_value": "YES"
        },
        {
          "additional_id": "DATABASEID",
          "additional_value": "7ktPA+Eaq+LM4vNMkQdbwBkUMDzzFYXmH+m21n3w5Rk="
        }
      ],
      "currency": "USD",
      "delivery_type": "Electronically",
      "discount": 0.0,
      "extended_download_price": 0.0,
      "manual_order_price": 0.0,
      "notification_no": 7944,
      "product_id": 301028317,
      "product_name": "AyaNova perpetual single user license includes one year maintenance plan ",
      "product_single_price": 24.0,
      "purchase_item_key": [],
      "quantity": 3,
      "running_no": 1,
      "shipping_price": 0.0,
      "shipping_vat_pct": 0.0,
      "subscription": {
        "expiration_date": "2024-01-14T06:17:59Z",
        "id": "841935113-1",
        "interval": "Yearly without end",
        "renewal_discount_count": "",
        "renewal_discount_start": "",
        "renewal_type": "auto",
        "retention_discount_count": "",
        "retention_discount_percent": "",
        "start_date": "2023-01-14T00:00:00",
        "status": "ToProcess",
        "status_id": "TOP"
      },
      "vat_pct": 7.0,
      "your_product_id": "perpetual"
    }
  ],
  "purchase_origin": "online",
  "sequential_invoice_no": "e5-US-2023-00000064245"
}
}
}


/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////    RAVEN MONTHLY SUBSCRIPTION 
{
"creation_date": "2023-01-07T01:54:11Z",
"id": 356798113,
"order_notification": {
"purchase": {
  "customer_data": {
    "billing_contact": {
      "address": {
        "city": "UNIONVILLE",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "L3R 9W6",
        "state": "Ontario",
        "state_id": "ON",
        "street1": "4261 HWY 7 E, Unit A14 #399"
      },
      "company": "sportseffect",
      "email": "service@sportseffect.com",
      "first_name": "Mark",
      "last_name": "Hopkins"
    },
    "customer_payment_data": {
      "currency": "CAD",
      "payment_method": "Visa"
    },
    "delivery_contact": {
      "address": {
        "city": "UNIONVILLE",
        "country": "Canada",
        "country_id": "CA",
        "postal_code": "L3R 9W6",
        "state": "Ontario",
        "state_id": "ON",
        "street1": "4261 HWY 7 E, Unit A14 #399"
      },
      "company": "sportseffect",
      "email": "service@sportseffect.com",
      "first_name": "Mark",
      "last_name": "Hopkins"
    },
    "language": "English",
    "language_iso": "en",
    "reg_name": "sportseffect",
    "shopper_id": "65387076",
    "subscribe_newsletter": false,
    "user_id": "service@sportseffect.com"
  },
  "is_test": false,
  "payment_complete_date": "2023-01-07T01:54:11Z",
  "payment_status": "complete",
  "payment_status_id": "PCA",
  "purchase_date": "2023-01-07T01:54:09Z",
  "purchase_id": 840549123,
  "purchase_item": [
    {
      "accounting": {
        "currency": "USD",
        "product_net": 23.8,
        "discount": 0.0,
        "product_vat": 3.09,
        "shipping": 0.0,
        "shipping_vat": 0.0,
        "eu_vat": -3.09,
        "margin_net": -4.03,
        "your_revenue": 19.77
      },
      "additional_information": [
        {
          "additional_id": "AGREENOREFUNDS",
          "additional_value": "YES"
        },
        {
          "additional_id": "AGREEPAYMETHODVALIDCANCEL",
          "additional_value": "YES"
        },
        {
          "additional_id": "AGREEEXPIRESIFNOTPAID",
          "additional_value": "YES"
        },
        {
          "additional_id": "DATABASEID",
          "additional_value": "New subscription"
        }
      ],
      "currency": "USD",
      "delivery_type": "Electronically",
      "discount": 0.0,
      "extended_download_price": 0.0,
      "manual_order_price": 0.0,
      "notification_no": 7937,
      "product_id": 301028467,
      "product_name": "AyaNova subscription one user monthly",
      "product_single_price": 11.9,
      "purchase_item_key": [],
      "quantity": 2,
      "running_no": 1,
      "shipping_price": 0.0,
      "shipping_vat_pct": 0.0,
      "subscription": {
        "expiration_date": "2023-02-07T00:15:13Z",
        "id": "833674953-1",
        "interval": "Monthly without end",
        "original_notification_no": "7925",
        "original_purchase_id": "833674953",
        "original_running_no": "1",
        "renewal_discount_count": "",
        "renewal_discount_start": "",
        "renewal_type": "auto",
        "retention_discount_count": "",
        "retention_discount_percent": "",
        "start_date": "2022-12-07T00:00:00",
        "status": "ToProcess",
        "status_id": "TOP"
      },
      "vat_pct": 13.0,
      "your_product_id": "subscriptionmonthly"
    }
  ],
  "purchase_origin": "Subscription",
  "sequential_invoice_no": "e5-DE-2023-00000055949"
}
}
}

        */

        #endregion sample vendor notifications
        //order notification json schema on this page down
        //actual schema: https://api.shareit.com/xml/2.4/ordernotification.xsd
        //https://account.mycommerce.com/home/wiki/7479997 //json format
        //https://account.mycommerce.com/home/wiki/7479805 //overall info






        /////////////////////////////////////////////////////////////////////

    }//eoc


}//eons

