using collAnon.Pub.Shared;
using drinkMe.Server.Controllers;
using drinkMe.Server.Services.Interfaces;
using drinkMe.Shared;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;

namespace drinkMe.Server.Tests
{
	public class DrinksControllerTest
	{
		readonly IDataService DataService;
		readonly IPaymentService PaymentService;

		public DrinksControllerTest(IDataService dataService, IPaymentService paymentService)
		{
			DataService = dataService;
			PaymentService = paymentService;
		}

		[Theory]
		[InlineData("D1AMOND_HANDS")]
		public async Task IsValidDiscountCode_Test_DiscountFound(string code)
		{
			var controller = new DrinksController(DataService, PaymentService);
			Assert.NotNull(controller);
			var result = await controller.IsValidDiscountCode(code);
			Assert.NotNull(result);
			Assert.IsType<OkObjectResult>(result);
			var okResult = result as OkObjectResult;
			Assert.NotNull(okResult.Value);
			Assert.Equal(okResult.StatusCode, StatusCodes.Status200OK);
			Assert.IsType<DiscountCodeViewModel>(okResult.Value);
			var discountCodeData = okResult.Value as DiscountCodeViewModel;
			Assert.Equal(discountCodeData.Code, code);
		}

		[Theory]
		[InlineData("NOT_MY_D4Y")]
		public async Task IsValidDiscountCode_Test_DiscountNotFound(string code)
		{
			var controller = new DrinksController(DataService, PaymentService);
			Assert.NotNull(controller);
			var result = await controller.IsValidDiscountCode(code);
			Assert.NotNull(result);
			Assert.IsType<ObjectResult>(result);
			var objectResult = result as ObjectResult;
			Assert.NotNull(objectResult.Value);
			Assert.Equal(objectResult.StatusCode, StatusCodes.Status404NotFound);
			Assert.IsType<WebResult>(objectResult.Value);
			var webResult = objectResult.Value as WebResult;
			Assert.False(webResult.IsValid);
			Assert.Equal(webResult.StatusCode, StatusCodes.Status404NotFound);
		}

		[Fact]
		public async Task GetDrinks_Test_NotEmpty()
		{
			var controller = new DrinksController(DataService, PaymentService);
			Assert.NotNull(controller);
			var result = await controller.GetDrinks();
			Assert.NotNull(result);
			Assert.IsType<OkObjectResult>(result);
			var okResult = result as OkObjectResult;
			Assert.NotNull(okResult.Value);
			Assert.Equal(okResult.StatusCode, StatusCodes.Status200OK);
			Assert.IsType<DrinkViewModel[]>(okResult.Value);
			var drinks = okResult.Value as DrinkViewModel[];
			Assert.NotEmpty(drinks);
		}

		[Fact]
		public async Task Pay_Test_WithSuccess()
		{
			var purchaseCart = new PurchaseCart
			{
				IsPayedWithCash = true,
				PurchasingItems = new List<CartItem>
				{
					new CartItem
					{
						 Id = 1,
						Quantity = 1
					}
				}
			};
			var controller = new DrinksController(DataService, PaymentService);
			Assert.NotNull(controller);
			var result = await controller.Pay(purchaseCart);
			Assert.NotNull(result);
			Assert.IsType<OkResult>(result);
			var okResult = result as OkResult;
			Assert.Equal(okResult.StatusCode, StatusCodes.Status200OK);
		}

		[Fact]
		public async Task Pay_Test_WithSuccess2()
		{
			var purchaseCart = new PurchaseCart
			{
				IsPayedWithCash = false,
				CreditCardNumber = "4000123412341234",
				CreditCardExpirationYear = "22",
				CreditCardCVVCode = "333",
				CreditCardExpirationMonth = "01",
				PurchasingItems = new List<CartItem>
				{
					new CartItem
					{
						 Id = 1,
						Quantity = 1
					}
				}
			};
			var controller = new DrinksController(DataService, PaymentService);
			Assert.NotNull(controller);
			var result = await controller.Pay(purchaseCart);
			Assert.NotNull(result);
			Assert.IsType<OkResult>(result);
			var okResult = result as OkResult;
			Assert.Equal(okResult.StatusCode, StatusCodes.Status200OK);
		}

		[Fact]
		public async Task Pay_Test_WithoutSuccess()
		{
			var purchaseCart = new PurchaseCart
			{
				IsPayedWithCash = false
			};
			var controller = new DrinksController(DataService, PaymentService);
			Assert.NotNull(controller);
			var result = await controller.Pay(purchaseCart);
			Assert.NotNull(result);
			Assert.IsType<BadRequestObjectResult>(result);
			var badResult = result as BadRequestObjectResult;
			Assert.NotNull(badResult.Value);
			Assert.IsType<WebResult>(badResult.Value);
			Assert.Equal(badResult.StatusCode, StatusCodes.Status400BadRequest);
			var webResult = badResult.Value as WebResult;
			Assert.False(webResult.IsValid);
			Assert.Equal(webResult.StatusCode, StatusCodes.Status400BadRequest);
		}
	}
}
