using AsbCloudApp.Data.DrillTestReport;
using AsbCloudApp.Services;
using ClosedXML.Excel;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudInfrastructure.Services.DrillTestReport
{
    public class DrillTestReportMakerService : IReportMakerService<DrillTestReportDataDto>
    {
        private readonly string templateName = "DrillTestReportTemplate.xlsx";
        private readonly string sheetName = "Лист1";
        private readonly int startRowNumber = 8;

        public async Task<Stream> MakeReportAsync(DrillTestReportDataDto report, CancellationToken cancellationToken)
        {
            using var excelTemplateStream = await Assembly.GetExecutingAssembly().GetTemplateCopyStreamAsync(templateName, cancellationToken);

            using var workbook = new XLWorkbook(excelTemplateStream, XLEventTracking.Disabled);

            AddToWorkbook(workbook, report);

            MemoryStream memoryStream = new MemoryStream();
            workbook.SaveAs(memoryStream, new SaveOptions { });
            memoryStream.Seek(0, SeekOrigin.Begin);

            return memoryStream;
        }


        private void AddToWorkbook(XLWorkbook workbook, DrillTestReportDataDto report)
        {
            var drillTestEntities = report.Data.Params;
            if (!drillTestEntities.Any())
                return;

            var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetName)
                        ?? throw new FileFormatException($"Книга excel не содержит листа {sheetName}.");

            sheet.Cell(4, 2).Value = report.Caption;
            sheet.Cell(5, 2)._SetValue(report.Date, setAllBorders: false);

            var rowNumber = startRowNumber;

            var stepWithMaxDepthSpeed = drillTestEntities.OrderByDescending(p => p.DepthSpeed).FirstOrDefault()!.Step;
            var startDepth = report.Data.DepthStart;
            var startDate = report.Data.TimeStampStart;

            foreach (var drillTestEntity in drillTestEntities)
            {
                var endDepth = startDepth + (drillTestEntity.DepthDrillStep ?? 0);
                var endDateTime = startDate.AddSeconds(drillTestEntity.TimeDrillStep ?? 0);

                sheet.Cell(rowNumber, 2).Value = startDepth;

                sheet.Cell(rowNumber, 3).Value = endDepth;

                sheet.Cell(rowNumber, 4).Value = drillTestEntity.DepthDrillStep;

                sheet.Cell(rowNumber, 5).Value = drillTestEntity.Workload;

                sheet.Cell(rowNumber, 6).Value = drillTestEntity.Speed;

                var cell = sheet.Cell(rowNumber, 7);
                cell._SetValue(startDate.DateTime);

                cell = sheet.Cell(rowNumber, 8);
                cell._SetValue(endDateTime.DateTime);

                sheet.Cell(rowNumber, 9).Value = Math.Round((drillTestEntity.TimeDrillStep ?? 0) / (60 * 60), 2);

                sheet.Cell(rowNumber, 10).Value = drillTestEntity.DepthSpeed;

                if (drillTestEntity.Step == stepWithMaxDepthSpeed)
                {
                    var currentCells = sheet.Row(rowNumber).Cells(1, 10);
                    currentCells.Style.Fill.BackgroundColor = XLColor.Yellow;
                }

                startDepth = endDepth;
                startDate = endDateTime;
                rowNumber++;
            }
        }
    }
}