using System;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using log4net;
using LeafWeb.Core.Entities;
using LeafWeb.Core.Utility;
using LeafWeb.WebCms.App_Start;
using LeafWeb.WebCms.Models;

namespace LeafWeb.WebCms.Controllers
{
	public class LeafInputController : BaseController
	{
		public ActionResult Create()
		{
			// initialize the session storage to retain SessionID between requests
			if (Session != null)
				Session["placeholder"] = 0;

			var viewModel = new LeafInputCreate();
			HydrateCreateViewModel(viewModel);
			return PartialView(viewModel);
		}

		[HttpPost]
		public ActionResult Submit(LeafInputCreate viewModel)
		{
			// directory name is the sessionID
			var files = GetBackloadDirectoryFiles(Session.SessionID);

			if (!files.Any())
				ModelState.AddModelError("Files", "Must select at least one file");

			// TODO: this keeps randomly not being mapable because string->bool binding fails. WHY
			if (ModelState.ContainsKey("TermsOfService"))
				ModelState["TermsOfService"].Errors.Clear();

			if (ModelState.IsValid) // HttpParamMatch indicates it's backing out from Confirm
			{
				// convert viewModel into Model
				var leafInput = viewModel.GetLeafInput(DataService);

				// load files into LeafInputFile
				leafInput.InputFiles =
					(from f in files
					 let bytes = System.IO.File.ReadAllBytes(f.FullName)
					 select new LeafInputFile { Filename = f.Name, Contents = bytes }).ToList();

				// Save to db
				DataService.AddLeafInput(leafInput);

				DeleteBackloadDirectory(Session.SessionID);

				var msg = $"A data set has submitted for '{viewModel.Identifier}' from '{viewModel.SiteId}'. " + Environment.NewLine
							+ $"When complete, an email will be delivered to {viewModel.Name} <{viewModel.Email}> with results.";

				SetStatusMessage(HttpUtility.HtmlEncode(msg), StatusType.Success);

				var logger = LogManager.GetLogger(GetType());
				logger.Info($"LeafInput: {leafInput.Id} Added, {leafInput.Identifier}, {leafInput.SiteId}, {leafInput.Email}");
				logger.Info($"LeafInputFiles: {leafInput.InputFiles.Select(f => f.Id.ToString()).Join(", ")}, Queued");

				HangfireStartup.TriggerPiscalProcessQueue();

				return RedirectToCurrentUmbracoPage();
			}

			HydrateCreateViewModel(viewModel);
			return CurrentUmbracoPage();
		}

		private void HydrateCreateViewModel(dynamic viewModel)
		{
			if (viewModel.PhotosynthesisType == null)
				viewModel.PhotosynthesisType = new SelectListViewModel();
			if (viewModel.PhotosynthesisType.ListItems == null)
				viewModel.PhotosynthesisType.ListItems = GetPhotosynthesisTypeSelectList();
		}

		// Callback from Piscal
		[ActionLog]
		public void NotifyComplete()
		{
			HangfireStartup.TriggerPiscalProcessQueue();
		}

		private FileInfo[] GetBackloadDirectoryFiles(string directoryName)
		{
			var path = Path.Combine(Server.MapPath("~/Files/"), directoryName + "\\");
			var directory = new DirectoryInfo(path);
			return
				!directory.Exists
				? new FileInfo[] { }
				: directory.GetFiles();
		}

		private void DeleteBackloadDirectory(string directoryName)
		{
			var path = Path.Combine(Server.MapPath("~/Files/"), directoryName + "\\");
			var directory = new DirectoryInfo(path);
			if (directory.Exists)
				directory.Delete(true);
		}
	}
}