using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using ServiceStack;
using ServiceStack.Stripe;
using ServiceStack.Stripe.Types;

namespace Stripe.Tests
{
    public class TestsBase
    {
        //Register License Key in SERVICESTACK_LICENSE Environment Variable or in App.config, test account team@
        protected readonly StripeGateway gateway = new StripeGateway("sk_test_Q9XojyuQxzWqe8b2rm6Vodna");

        protected StripeCustomer CreateCustomer()
        {
            var customer = gateway.Post(CreateStripeCustomerRequest());
            return customer;
        }

        protected async Task<StripeCustomer> CreateCustomerAsync()
        {
            var customer = await gateway.PostAsync(CreateStripeCustomerRequest());
            return customer;
        }

        protected static CreateStripeCustomer CreateStripeCustomerRequest()
        {
            return new CreateStripeCustomer
            {
                AccountBalance = 10000,
                Source = new StripeCard
                {
                    Name = "Test Card",
                    Number = "4242424242424242",
                    Cvc = "123",
                    ExpMonth = 1,
                    ExpYear = 2030,
                    AddressLine1 = "1 Address Road",
                    AddressLine2 = "12345",
                    AddressZip = "City",
                    AddressState = "NY",
                    AddressCountry = "US",
                },
                Shipping = new StripeShipping
                {
                    Name = "Ship To",
                    Phone = "555-5555-5555",
                    Address = new StripeAddress
                    {
                        Line1 = "1 Address Road",
                        Line2 = "12345",
                        City = "City",
                        State = "NY",
                        Country = "US",
                    },
                },
                Description = "Description",
                Email = "test@email.com",
            };
        }

        protected StripeCoupon CreateCoupon()
        {
            var coupon = gateway.Post(new CreateStripeCoupon
            {
                Id = "TEST-COUPON-01",
                Duration = StripeCouponDuration.repeating,
                PercentOff = 20,
                Currency = "usd",
                DurationInMonths = 2,
                RedeemBy = DateTime.UtcNow.AddYears(1),
                MaxRedemptions = 10,
            });
            return coupon;
        }

        protected StripeCoupon GetOrCreateCoupon()
        {
            try
            {
                return gateway.Get(new GetStripeCoupon { Id = "TEST-COUPON-01" });
            }
            catch (StripeException ex)
            {
                if (ex.StatusCode == HttpStatusCode.NotFound)
                    return CreateCoupon();

                throw;
            }
        }

        protected StripePlan GetOrCreatePlan(string id = "TEST-PLAN-01")
        {
            try
            {
                return gateway.Get(new GetStripePlan { Id = id });
            }
            catch (StripeException ex)
            {
                if (ex.StatusCode == HttpStatusCode.NotFound)
                    return CreatePlan(id);

                throw;
            }
        }

        protected StripePlan CreatePlan(string id = "TEST-PLAN-01")
        {
            try
            {
                var product = gateway.Send(new GetStripeProduct { Id = id });
                if (product != null)
                {
                    gateway.Send(new DeleteStripeProduct { Id = id });
                }
            }
            catch (StripeException ex)
            {
                if (ex.StatusCode != HttpStatusCode.NotFound)
                    throw;
            }

            var plan = gateway.Post(new CreateStripePlan
            {
                Id = id,
                Amount = 10000,
                Currency = "usd",
                Nickname = "Test Plan",
                Product = new StripePlanProduct
                {
                    Id = id,
                    Name = "Test Plan Product",
                },
                Interval = StripePlanInterval.month,
                IntervalCount = 1,
            });
            return plan;
        }

        protected StripeProduct GetOrCreateProduct(string id = "TEST-PRODUCT-01")
        {
            try
            {
                return gateway.Get(new GetStripeProduct { Id = id });
            }
            catch (StripeException ex)
            {
                if (ex.StatusCode == HttpStatusCode.NotFound)
                    return CreateProduct(id);

                throw;
            }
        }
        protected StripeProduct CreateProduct(string id = "TEST-PRODUCT-01")
        {
            var createStripeProduct = new CreateStripeProduct
            {
                Id = id,
                Name = "Test Product",
                Active = true,
                Attributes = new[] { "foo", "bar" },
                Caption = "Product Caption",
                Description = "Product Description",
                Images = new[] { "http://url.to/img.jpg" },
                Metadata = new Dictionary<string, string>
                {
                    {"foo", "bar"}
                },
                PackageDimensions = new StripePackageDimensions
                {
                    Height = 100,
                    Width = 200,
                    Length = 300,
                    Weight = 400,
                },
                Shippable = true,
                Type = StripeProductType.good,
                //StatementDescriptor = "Product Descriptor",  only for `service`
                Url = "http://url.to/product",
            };
            var product = gateway.Send(createStripeProduct);
            return product;
        }
    }
}