using Adaptation.Shared;
using Adaptation.Shared.Methods;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;

namespace Adaptation.FileHandlers.ConvertExcelToJson;

public class ProcessData : IProcessData
{

    private readonly List<object> _Details;

    List<object> Shared.Properties.IProcessData.Details => _Details;

    public ProcessData(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection, string sheetName)
    {
        fileInfoCollection.Clear();
        _Details = new List<object>();
        Parse(fileRead, logistics, fileInfoCollection, sheetName);
    }

    string IProcessData.GetCurrentReactor(IFileRead fileRead, Logistics logistics, Dictionary<string, string> reactors)
        => throw new Exception(string.Concat("See ", nameof(Parse)));

    Tuple<string, Test[], JsonElement[], List<FileInfo>> IProcessData.GetResults(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection)
        => new(logistics.Logistics1[0], Array.Empty<Test>(), Array.Empty<JsonElement>(), fileInfoCollection);

#nullable enable

    /// <summary>
    /// https://social.msdn.microsoft.com/Forums/en-US/2e030743-5d66-4e53-bbff-bb2eee0cbc9b/readingwriting-excel-without-excel?forum=Vsexpressvcs
    /// </summary>
    private static DataTable GetSheet(string file, string selectSql)
    {
        DataTable results = new();
#if Linux
            ()("Built on Linux!");
#elif OSX
            ()("Built on macOS!");
#elif Windows || !NETCORE
#pragma warning disable CA1416
        for (int i = 0; i < int.MaxValue; i++)
        {
            try
            {
                OleDbConnectionStringBuilder connectionStringBuilder = new()
                {
                    Provider = "Microsoft.ACE.OLEDB.12.0",
                    DataSource = file
                };
                connectionStringBuilder.Add("Extended Properties", "Excel 12.0 Xml;HDR=YES;IMEX=1;ReadOnly=1;");
                using OleDbConnection connection = new(connectionStringBuilder.ConnectionString);
                connection.Open();
                using (OleDbDataAdapter adapter = new(selectSql, connection))
                    adapter.Fill(results);
                connection.Close();
                break;
            }
            catch (Exception)
            {
                if (i > 3) //2019-12-28 - 001
                    throw;
                System.Threading.Thread.Sleep(1000);
            }
#pragma warning restore CA1416
        }
#else
            ()("Built in unknown!");
#endif
        return results;
    }

    public static string DataTableToJSON(DataTable table)
    {
        string name;
        string value;
        object @object;
        StringBuilder jsonString = new();
        if (table.Rows.Count > 0)
        {
            _ = jsonString.Append('[');
            for (int i = 0; i < table.Rows.Count; i++)
            {
                _ = jsonString.Append('{');
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    @object = table.Rows[i][j];
                    if (@object is null)
                        value = string.Empty;
                    else
                        value = string.Concat(@object);
                    if (value.Contains("\""))
                        value = value.Replace("\"", "\\\"");
                    if (value.Contains("\n"))
                        value = value.Replace("\n", "<br />");
                    name = table.Columns[j].ColumnName.ToString();
                    if (name == ",")
                        name = "Title";
                    if (name.Contains("\""))
                        name = name.Replace("\"", "\\\"");
                    if (name.Contains("\n"))
                        name = name.Replace("\n", "<br />");
                    _ = jsonString.Append('"').Append(name).Append("\":").Append('"').Append(value).Append('"');
                    if (j < table.Columns.Count - 1)
                        _ = jsonString.Append(',');
                }
                if (i == table.Rows.Count - 1)
                    _ = jsonString.Append('}');
                else
                    _ = jsonString.Append("},");
            }
            _ = jsonString.Append(']');
        }
        return jsonString.ToString();
    }

    private void Parse(IFileRead fileRead, Logistics logistics, List<FileInfo> fileInfoCollection, string sheet)
    {
        if (fileRead is null)
            throw new NullReferenceException();
        if (fileInfoCollection is null)
            throw new NullReferenceException();
        string selectSql = string.Concat("SELECT * FROM [", sheet, "$]");
        DataTable dataTable = GetSheet(logistics.ReportFullPath, selectSql);
        if (dataTable.Rows.Count == 0)
            throw new Exception("No rows");
        string json = DataTableToJSON(dataTable);
        FIBacklogMesa[]? fIBacklogMesaCollection = JsonSerializer.Deserialize<FIBacklogMesa[]>(json, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
        if (fIBacklogMesaCollection is null || !fIBacklogMesaCollection.Any())
            throw new NullReferenceException();
        json = JsonSerializer.Serialize(fIBacklogMesaCollection.OrderBy(l => l.Req), new JsonSerializerOptions() { WriteIndented = true });
        _Details.Add(json);
    }

}