using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Model.Models.VitrosModels;

namespace VitrosConsole.Parser
{
    public class VitrosParser
    {
        private readonly ILogger _logger;

        public VitrosParser(ILogger<VitrosParser> logger)
        {
            _logger = logger;
        }

        public List<Sample> Parse(string filePath)
        {
            IEnumerable<string> reportDataLines = ReadDataFromFile(filePath);

            List<Sample> samples = GetSampleData(reportDataLines);
            samples = RemoveDuplicateSamples(samples);
            return samples;
        }

        private List<Sample> GetSampleData(IEnumerable<string> reportDataLines)
        {
            List<Sample> samples = new List<Sample>();
            Sample sample = new Sample();
            foreach (string line in reportDataLines.Where(l => l.Length > 1))
            {
                if (line.Substring(4, 1) == RecordType.HeaderRecord)
                {
                    sample = new Sample();
                   // sample.Analyzer = line.Substring(11, 6);
                    string date = line.Substring(23, 6);
                    sample.DateTime = DateTime.ParseExact(date, "yyMMdd", CultureInfo.InvariantCulture);
                    string time = line.Substring(17, 6);

                    sample.DateTime += new TimeSpan(Convert.ToInt32(time.Substring(0, 2)), Convert.ToInt32(time.Substring(2, 2)), Convert.ToInt32(time.Substring(4, 2)));

                    switch (line.Substring(44, 1))
                    {
                        case "1":
                            sample.Fluid = FluidType.Serum;
                            break;
                        case "2":
                            sample.Fluid = FluidType.CSF;
                            break;
                        case "3":
                            sample.Fluid = FluidType.Urine;
                            break;
                    }
                    sample.Quadrant = line.Substring(44, 1);
                    sample.Cup = line.Substring(46, 2);
                    sample.TrayName = line.Substring(48, 15).All(c => Char.IsWhiteSpace(c)) == true ? "No Tray Name" : line.Substring(48, 15);
                    sample.StatFlag = line.Substring(63, 1);
                    sample.ControlFlag = line.Substring(64, 1);
                    sample.Mode = line.Substring(65, 1) == "0" ? Mode.Select : Mode.Batch;
                    sample.DilutionFactor = line.Substring(66, 7);
                    sample.BarCodeNumber = line.Substring(29, 15);
                    samples.Add(sample);

                }
                if (line.Substring(4, 1) == RecordType.TestResultRecord)
                {
                    Result result = new Result
                    {
                        Test = line.Substring(5, 4).Trim(),

                        Value = line.Substring(9, 8),// line.Substring(9, 9)

                        Unit = line.Substring(17, 7),  //line.Substring(18, 8)

                        ErrorFlag = line.Substring(25, 1), //line.Substring(26, 1)

                        Error = Result.ErrorTypes.FirstOrDefault(e => e.Key == line.Substring(25, 1)).Value,

                        WarningFlag = line.Substring(26, 1), //line.Substring(27, 1)

                        Warning = Result.WarningTypes.FirstOrDefault(w => w.Key == line.Substring(26, 1)).Value
                    };
                    sample.Results.Add(result);

                }
            }
            return samples;
        }

        private List<Sample> RemoveDuplicateSamples(IEnumerable<Sample> data)
        {
            return data.GroupBy(s => s.BarCodeNumber)
                       .Select(g => g.FirstOrDefault())
                       .ToList();
        }

        private List<string> ReadDataFromFile(string fileName)
        {
            try
            {
                List<string> listString = new List<string>();
                //string sourceFile = System.IO.Path.Combine(fileName);
                using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    StreamReader sr = new StreamReader(fs);
                    while (true)
                    {
                        string line = sr.ReadLine();
                        if (line == null)
                            break;
                        listString.Add(line);
                    }
                    sr.Close();
                }

                return listString;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                throw;
            }
        }
    }
}
