using System.Collections.Generic;
using System.IO;
using System.Linq;
using AutoMapper;
using ClosedXML.Excel;
using CsvHelper;
using CsvHelper.Configuration;
using CsvHelper.Excel;
using InventoryTraker.Web.Models;

namespace InventoryTraker.Web.Utilities
{
	public class DistributionReportWriter
	{
		public class DistributionReportExportItem
		{
			public string Name { get; set; }
			public string UnitsPerCaseContainerType { get; set; }
			public string ExpirationDate { get; set; }
			public string RemovedQuantity { get; set; }
			public string UnitQuantity { get; set; }
			public string Weight { get; set; }

			public class AutoMapperProfile : Profile
			{
				public AutoMapperProfile()
				{
					CreateMap<TransactionViewModel, DistributionReportExportItem>()
					.ForMember(d => d.Name, opt => opt.MapFrom(i => i.Name))
					.ForMember(d => d.UnitsPerCaseContainerType,
						opt => opt.MapFrom(i => $"{i.UnitsPerCase} / {i.ContainerType}"))
					.ForMember(d => d.ExpirationDate,
						opt => opt.MapFrom(i => i.ExpirationDate.ToShortDateString()))
					.ForMember(d => d.UnitQuantity,
						opt => opt.MapFrom(i => i.RemovedQuantity * i.UnitsPerCase))
					.ForMember(d => d.Weight,
						opt => opt.MapFrom(i => $"{i.WeightPerCase * i.RemovedQuantity:0} lbs"));
				}
			}
		}

		private sealed class DistributionReportMap : CsvClassMap<DistributionReportExportItem>
		{
			public DistributionReportMap()
			{
				Map(m => m.Name).Name("Name of Commodity");
				Map(m => m.UnitsPerCaseContainerType).Name("Pack Size / Units per Case");
				Map(m => m.ExpirationDate).Name("Expiration Date");
				Map(m => m.RemovedQuantity).Name("Case Quantity");
				Map(m => m.UnitQuantity).Name("Unit Quantity");
				Map(m => m.Weight).Name("Weight");
			}
		}

		private readonly IMapper _mapper;

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

		public byte[] Write(IEnumerable<DistributionReport> reports)
		{
			using (var stream = new MemoryStream())
			{
				WriteStream(reports, stream);
				return stream.ToArray();
			}
		}

		public void WriteStream(IEnumerable<DistributionReport> reports, Stream stream)
		{
			using (var workbook = new XLWorkbook(XLEventTracking.Disabled))
			{
				var worksheet = workbook.AddWorksheet("Distribution Report");
				using (var writer = new CsvWriter(new ExcelSerializer(worksheet)))
				{
					writer.Configuration.RegisterClassMap(new DistributionReportMap());

					foreach (var report in reports)
					{
						writer.WriteField(report.Destination);
						writer.NextRecord();
						writer.WriteField(report.Date.ToShortDateString());
						writer.NextRecord();
						var items =
							_mapper.Map<IEnumerable<TransactionViewModel>, IEnumerable<DistributionReportExportItem>>
								(report.Transactions)
								.OrderBy(i => i.Name);
						writer.WriteRecords(items);
					}
					workbook.SaveAs(stream);
				}
			}
		}
	}
}