using System.IO;
using ConeCalorimeter.Models;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;

namespace ConeCalorimeter.Services;

public sealed class NpoiRealtimeDataExportService : IRealtimeDataExportService
{
    private static readonly string[] Headers =
    [
        "Time(s)",
        "O2 (%)",
        "CO2 (%)",
        "CO (%)",
        "吸光率%",
        "孔板压差 (Pa)",
        "孔板温度 (K)",
        "HRR",
        "THR (MJ/m2)",
        "SPR",
        "TSR (m2)",
        "MLR (g/s)",
        "热释放KW/m2",
        "EHC",
        "损失质量"
    ];

    public void Export(string outputPath, IReadOnlyList<RealtimeDataRecord> records)
    {
        var workbook = new HSSFWorkbook();
        var sheet = workbook.CreateSheet("实时数据");

        WriteHeader(sheet);
        WriteRecords(sheet, records);

        using var outputStream = File.Create(outputPath);
        workbook.Write(outputStream);
    }

    private static void WriteHeader(ISheet sheet)
    {
        var row = sheet.CreateRow(0);
        for (var i = 0; i < Headers.Length; i++)
        {
            row.CreateCell(i).SetCellValue(Headers[i]);
        }
    }

    private static void WriteRecords(ISheet sheet, IReadOnlyList<RealtimeDataRecord> records)
    {
        for (var i = 0; i < records.Count; i++)
        {
            var record = records[i];
            var row = sheet.CreateRow(i + 1);

            SetNumeric(row, 0, record.TestSeconds >= 0 ? record.TestSeconds : double.NaN);
            SetNumeric(row, 1, record.Oxygen);
            SetNumeric(row, 2, record.CarbonDioxide);
            SetNumeric(row, 3, record.CarbonMonoxide);
            SetNumeric(row, 4, record.Absorbance);
            SetNumeric(row, 5, record.OrificePressure);
            SetNumeric(row, 6, record.OrificeTemperature);
            SetNumeric(row, 7, record.HeatReleaseRate);
            SetNumeric(row, 8, record.TotalHeatRelease);
            SetNumeric(row, 9, record.SmokeProduction);
            SetNumeric(row, 10, record.TotalSmoke);
            SetNumeric(row, 11, record.MassLossRate);
            SetNumeric(row, 12, record.HeatReleaseRateKw);
            SetNumeric(row, 13, record.EffectiveHeatOfCombustion);
            SetNumeric(row, 14, record.MassLoss);
        }

        for (var i = 0; i < Headers.Length; i++)
        {
            sheet.AutoSizeColumn(i);
        }
    }

    private static void SetNumeric(IRow row, int columnIndex, double value)
    {
        if (double.IsFinite(value))
        {
            row.CreateCell(columnIndex).SetCellValue(value);
        }
    }
}
