using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using InventoryTraker.Web.Core;
using InventoryTraker.Web.Data;
using InventoryTraker.Web.Identity;
using InventoryTraker.Web.Utilities;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;

namespace InventoryTraker.Web.Migrations
{
	public static class SeedData
	{
		public static void Init()
		{
			using (var context = new AppDbContext())
				Init(context);
		}

		public static void Init(AppDbContext context)
		{
			if (!context.Users.Any())
			{
				var manager = new ApplicationUserManager(new UserStore<User>(context), null);
				manager.Create(new User
				{
					Email = "james.kolpack@gmail.com",
					UserName = "James Kolpack",
				}, "hgBdFiJTK");

				manager.Create(new User
				{
					Email = "bbanegas@ethra.org",
					UserName = "Brandi Banegas",
				}, "3v9qxe");

				manager.Create(new User
				{
					Email = "ccecil@ethra.org",
					UserName = "Cyndie Cecil",
				}, "95kdsxa");

				manager.Create(new User
				{
					Email = "knorton@ethra.org",
					UserName = "Kay Norton",
				}, "rt9pmz1");
			}

			if (!context.Inventories.Any())
			{
				AddInventoryTypes(context);

				context.SaveChanges();

				AddInventory(context);

				context.SaveChanges();
			}
		}

		private static void AddInventoryTypes(AppDbContext context)
		{
			var folder = HttpContext.Current.Server.MapPath("~/App_Data");
			var inventoryTypeFile = Path.Combine(folder, "InventoryTypeSeedData.xlsx");
			var parser = new InventoryTypeParser(new FileInfo(inventoryTypeFile));
			foreach (var inventoryType in parser.Parse())
			{
				context.InventoryTypes.Add(inventoryType);
			}
		}

		private static void AddInventory(AppDbContext context)
		{
			var r = new Random(1);
			var inventoryTypes = context.InventoryTypes.ToList();
			var counties = new List<string> {"Blount County", "Morgan County", "Knox County", "Anderson County", "Claiborne County", "Campbell County"};
			var colors = new List<string> {"Red", "Purple", "Blue", "Yellow", "White"};

			for (var dd = DateTime.Today.AddYears(-4); dd < DateTime.Today.AddMonths(-2); dd = dd.AddMonths(3))
			{
				ExprireLossInventory(context, dd, r);
				// add some inventory
				for (int i = 0; i < r.Next(5,10); i++)
				{
					var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count()));
					var addedDate = dd.AddDays(r.Next(-10, 10));
					var expiration = addedDate.AddMonths(r.Next(2, 48));
					var memo =
						r.Next(0, 3) > 0
							? colors.ElementAt(r.Next(0, colors.Count)) + $" {inventoryType.ContainerType}"
							: string.Empty;
					var quantity = r.Next(5, 112);

					var addedTransaction = new Transaction
					{
						TransactionType = TransactionType.Added,
						AddedQuantity = quantity,
						Memo = "Arrival",
						CurrentQuantity = quantity,
						TransactionDate = addedDate,
						Timestamp = addedDate
					};
					var inventory = new Inventory
					{
						InventoryType = inventoryType,
						ExpirationDate = expiration,
						AddedDate = addedDate,
						Memo = memo,
						Quantity = quantity,
						Transactions = new List<Transaction> {addedTransaction}
					};
					context.Inventories.Add(inventory);
				}
				dd = dd.AddDays(14);
				// expire/loss some inventory
				ExprireLossInventory(context, dd, r);

				dd = dd.AddDays(14);
				// distribute some inventory
				foreach (var destination in counties)
				{
					var availableInventories =
						context.Inventories.Local.Where(i => i.Quantity > 0).ToList();

					for (
						var i = r.Next(0, availableInventories.Count); 
						i < availableInventories.Count; 
						i += r.Next(1, availableInventories.Count / 2))
					{
						var inventory = availableInventories.ElementAt(i);
						if (inventory.ExpirationDate <= dd)
							continue;

						var quantityRemoved = r.Next(1, inventory.Quantity + 1);

						var transMemo = $"Distributed to {destination}";
						var transType = TransactionType.Distributed;

						var distributeTransaction = new Transaction
						{
							TransactionType = transType,
							RemovedQuantity = quantityRemoved,
							CurrentQuantity = inventory.Quantity - quantityRemoved,
							Inventory = inventory,
							Memo = transMemo,
							TransactionDate = dd,
							Timestamp = dd,
							Destination = destination
						};
						inventory.Quantity = distributeTransaction.CurrentQuantity;

						inventory.Transactions.Add(distributeTransaction);
					}
				}
				ExprireLossInventory(context, dd, r);
			}

			//for (int i = 0; i < 200; i++)
			//{
			//	var inventoryType = inventoryTypes.ElementAt(r.Next(0, context.InventoryTypes.Count()));
			//	var addedDate = DateTime.Today.AddMonths(-r.Next(1, 24));
			//	var expiration = addedDate.AddMonths(r.Next(2, 48));
			//	var memo = 
			//		r.Next(0,3) > 0 
			//		? colors.ElementAt(r.Next(0, colors.Count)) + $" {inventoryType.ContainerType}"
			//		: string.Empty;
			//	var quantity = r.Next(5, 112);

			//	var previousTransaction = new Transaction
			//	{
			//		TransactionType = TransactionType.Added,
			//		AddedQuantity = quantity,
			//		Memo = "Arrival",
			//		CurrentQuantity = quantity,
			//		TransactionDate = addedDate,
			//		Timestamp = addedDate
			//	};
			//	var inventory = new Inventory
			//	{
			//		InventoryType = inventoryType,
			//		ExpirationDate = expiration,
			//		AddedDate = addedDate,
			//		Memo = memo,
			//		Quantity = quantity,
			//		Transactions = new List<Transaction> { previousTransaction}
			//	};
			//	context.Inventories.Add(inventory);

			//	for (int j = 0; j < 5 && previousTransaction.CurrentQuantity > 0; j++)
			//	{
			//		var transactionDate = previousTransaction.TransactionDate.AddDays(r.Next(1, 100));
			//		if (transactionDate >= DateTime.Today)
			//			break;

			//		Transaction transaction;
			//		if (transactionDate >= expiration)
			//		{
			//			if (r.Next(1, 3) == 1)
			//				break;

			//transaction = new Transaction
			//{
			//	TransactionType = TransactionType.Expired,
			//	RemovedQuantity = previousTransaction.CurrentQuantity,
			//	CurrentQuantity = 0,
			//	Inventory = inventory,
			//	Memo = $"Expired on {expiration.ToShortDateString()}",
			//	TransactionDate = transactionDate,
			//	Timestamp = transactionDate
			//};
			//		}
			//		else
			//		{
			//			var quantityRemoved = r.Next(1, 100);
			//			if (quantityRemoved > previousTransaction.CurrentQuantity)
			//				quantityRemoved = previousTransaction.CurrentQuantity;

			//			var destination = counties.ElementAt(r.Next(0, counties.Count));
			//			var transMemo = $"Distributed to {destination}";
			//			var transType = TransactionType.Distributed;

			//			if (r.Next(1, 15) == 1)
			//			{
			//				transMemo = "Loss";
			//				transType = TransactionType.Loss;
			//			}

			//			transaction = new Transaction
			//			{
			//				TransactionType = transType,
			//				RemovedQuantity = quantityRemoved,
			//				CurrentQuantity = previousTransaction.CurrentQuantity - quantityRemoved,
			//				Inventory = inventory,
			//				Memo = transMemo,
			//				TransactionDate = transactionDate,
			//				Timestamp = transactionDate,
			//				Destination = destination
			//			};
			//		}

			//		inventory.Quantity = transaction.CurrentQuantity;

			//		inventory.Transactions.Add(transaction);

			//		previousTransaction = transaction;
			//	}
			//}
		}

		private static void ExprireLossInventory(AppDbContext context, DateTime dd, Random r)
		{
			var availableInventories =
				context.Inventories.Local.Where(i => i.Quantity > 0).ToList();

			foreach (var inventory in availableInventories)
			{
				if (inventory.ExpirationDate <= dd && r.Next(0, 4) > 0)
				{
					var expiredTransaction = new Transaction
					{
						TransactionType = TransactionType.Expired,
						RemovedQuantity = inventory.Quantity,
						CurrentQuantity = 0,
						Inventory = inventory,
						Memo = $"Expired on {inventory.ExpirationDate.ToShortDateString()}",
						TransactionDate = dd,
						Timestamp = dd
					};
					inventory.Quantity = expiredTransaction.CurrentQuantity;
					inventory.Transactions.Add(expiredTransaction);
				}
				else if (r.Next(0, 40) == 0)
				{
					var lossQty = r.Next(1, inventory.Quantity + 1);
					var lossTransaction = new Transaction
					{
						TransactionType = TransactionType.Loss,
						RemovedQuantity = lossQty,
						CurrentQuantity = inventory.Quantity - lossQty,
						Inventory = inventory,
						Memo = $"Missing",
						TransactionDate = dd,
						Timestamp = dd
					};
					inventory.Quantity = lossTransaction.CurrentQuantity;
					inventory.Transactions.Add(lossTransaction);
				}
			}
		}
	}
}