using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using AutoMapper;
using CsvHelper;
using InventoryTraker.Web.Core;
using InventoryTraker.Web.Models;
using InventoryTraker.Web.Utilities;

namespace InventoryTraker.Web.Services
{
	public class InventoryImporter
	{
		private readonly IMapper _mapper;

		public InventoryImporter(IMapper mapper)
		{
			_mapper = mapper;
		}

		public IEnumerable<Inventory> Import(FileSystemInfo excelFile)
		{
			var inventoryParser = new InventoryParser(excelFile);

			IList<InventoryAddForm> forms;
			try
			{
				forms = inventoryParser.Parse();
			}
			catch (CsvMissingFieldException e)
			{
				var fieldname = Regex.Replace(e.Message, ".*'(.*)'.*", "$1");

				throw new ImportException($"Cannot find required field titled '{fieldname}'", e);
			}
			//catch (CsvBadDataException e)
			//{
			//	throw new ImportException(e.Message, e);
			//}
			//catch (CsvParserException e)
			//{
			//	throw new ImportException(e.Message, e);
			//}
			//catch (CsvReaderException e)
			//{
			//	throw new ImportException(e.Message, e);
			//}
			catch (Exception e)
			{
				throw new ImportException(e.Message, e);
			}

			IList<Inventory> inventories = new List<Inventory>();
			var validationErrors = new List<string>();
			foreach (var addForm in forms)
			{
				var results = new List<ValidationResult>();
				var context = new ValidationContext(addForm, null, null);
				if (!Validator.TryValidateObject(addForm, context, results))
				{
					// results will contain all the failed validation errors.
					validationErrors.AddRange(
						results.Select(result => $"{addForm.Id} - ${result.ErrorMessage}")
						);
				}
				else
				{
					inventories.Add(_mapper.Map<Inventory>(addForm));
				}
			}

			if (validationErrors.Any())
			{
				throw new ImportException(string.Join(Environment.NewLine, validationErrors));
			}

			return inventories;
		}
	}
}