using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
using ClosedXML.Excel;

namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser;

public class WellOperationDefaultExcelParser : IWellOperationExcelParser<WellOperationImportDefaultOptionsDto>
{
    public SheetDto Parse(Stream stream, WellOperationImportDefaultOptionsDto options)
	{
		using var workbook = new XLWorkbook(stream);

		return ParseWorkbook(workbook, options);
	}

	private static SheetDto ParseWorkbook(IXLWorkbook workbook, WellOperationImportDefaultOptionsDto options)
	{
		var sheetName = options.IdType == WellOperation.IdOperationTypePlan
			? DefaultTemplateInfo.SheetNamePlan
			: DefaultTemplateInfo.SheetNameFact;
		
		var sheet = workbook.GetWorksheet(sheetName);
		
		return ParseSheet(sheet);
	}

	private static SheetDto ParseSheet(IXLWorksheet sheet)
	{
		if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
			throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");

		var count = sheet.RowsUsed().Count() - DefaultTemplateInfo.HeaderRowsCount;

		switch (count)
		{
			case > 1024:
				throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество операций.");
			case <= 0:
                return new SheetDto { Name = sheet.Name };
		}

		var rows = new RowDto[count];
		
		var cellValuesErrors = new List<string>();
		
		for (int i = 0; i < rows.Length; i++)
		{
			try
			{
				var xlRow = sheet.Row(1 + i + DefaultTemplateInfo.HeaderRowsCount);

				rows[i] = ParseRow(xlRow);
			}
			catch (FileFormatException ex)
			{
				cellValuesErrors.Add(ex.Message);
			}
		}
		
		if (cellValuesErrors.Any())
			throw new FileFormatException(string.Join("\r\n", cellValuesErrors));

		return new SheetDto
        {
			Name = sheet.Name,
			Rows = rows
        };
	}

	private static RowDto ParseRow(IXLRow xlRow)
	{
		return new RowDto
		{
			Number = xlRow.RowNumber(),
			Section = xlRow.Cell(DefaultTemplateInfo.ColumnSection).GetCellValue<string>(),
			Category = xlRow.Cell(DefaultTemplateInfo.ColumnCategory).GetCellValue<string>(),
			CategoryInfo = xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo).GetCellValue<string?>(),
			DepthStart = xlRow.Cell(DefaultTemplateInfo.ColumnDepthStart).GetCellValue<double>(),
			DepthEnd = xlRow.Cell(DefaultTemplateInfo.ColumnDepthEnd).GetCellValue<double>(),
			Date = xlRow.Cell(DefaultTemplateInfo.ColumnDate).GetCellValue<DateTime>(),
			Duration = xlRow.Cell(DefaultTemplateInfo.ColumnDuration).GetCellValue<double>(),
			Comment = xlRow.Cell(DefaultTemplateInfo.ColumnComment).GetCellValue<string?>()
		};
	}
}