using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Web;
using Aspose.Cells;
using Kreta.Core;
using Kreta.Core.ConnectionType;
using Kreta.Core.Exceptions;
using Kreta.DataAccessManual;
using Kreta.Resources;

namespace Kreta.BusinessLogic.Helpers
{
    public class ItmAdatszolgaltatasHelper : LogicBase
    {
        public ItmAdatszolgaltatasHelper(IConnectionType connectionType) : base(connectionType)
        {
        }

        public List<MemoryStream> IntezmenyAdatok()
        {
            var fenntartoNev = IntezmenyFenntarto();
            var itmAdatok = GetItmAdatok();

            if (itmAdatok.Tables.Count == 0 || itmAdatok.Tables[0].Rows.Count == 0)
            {
                throw new BlException(AdatszolgaltatasokResource.ItmAdatszolgaltatasNincsenekSzakkepesitesiAdatok);
            }

            var splittedMergedDataSet = SplitDataSet(MergeDataSet(fenntartoNev, AdatszolgaltatasokResource.ItmAdatszolgaltatasKepzesKezdete2122Osz, itmAdatok));

            return splittedMergedDataSet.Select(x => FillTemplate(x)).ToList();
        }

        private List<DataSet> SplitDataSet(DataSet itmAdatok, int darabMeret = 100)
        {
            var dataSetList = new List<DataSet>();

            var szelet = Math.Ceiling(itmAdatok.Tables[0].Rows.Count / (double)darabMeret);

            if (szelet == 1)
            {
                dataSetList.Add(itmAdatok);
            }
            else
            {
                for (int i = 0; i < szelet; i++)
                {
                    var dataSet = itmAdatok.Clone();

                    var kiNemSzedettDarabszam = itmAdatok.Tables[0].Rows.Count - (darabMeret * i);
                    var kiszedhetoDarabszam = darabMeret > kiNemSzedettDarabszam ? kiNemSzedettDarabszam : darabMeret;

                    for (int j = 0; j < kiszedhetoDarabszam; j++)
                    {
                        var kiszedesiPozicio = j + (i * darabMeret);

                        dataSet.Tables[0].ImportRow(itmAdatok.Tables[0].Rows[kiszedesiPozicio]);
                    }

                    dataSetList.Add(dataSet);
                }
            }

            return dataSetList;
        }

        private DataSet MergeDataSet(string fenntartoNev, string kepzesKedete, DataSet itmAdatok)
        {
            var mergedDataSet = itmAdatok.Copy();

            var kedvezmenyezettNeveOszlop = mergedDataSet.Tables[0].Columns.Add(AdatszolgaltatasokResource.ItmAdatszolgaltatasKedvezmenyezettNeveExcelAzonosito, typeof(string));
            kedvezmenyezettNeveOszlop.SetOrdinal(0);

            var kepzesKedeteOszlop = mergedDataSet.Tables[0].Columns.Add(AdatszolgaltatasokResource.ItmAdatszolgaltatasKepzesKezdeteExcelAzonosito, typeof(string));
            kepzesKedeteOszlop.SetOrdinal(2);

            foreach (DataRow item in mergedDataSet.Tables[0].Rows)
            {
                item.SetField<string>(AdatszolgaltatasokResource.ItmAdatszolgaltatasKedvezmenyezettNeveExcelAzonosito, fenntartoNev);
                item.SetField<string>(AdatszolgaltatasokResource.ItmAdatszolgaltatasKepzesKezdeteExcelAzonosito, kepzesKedete);
            }

            return mergedDataSet;
        }

        private MemoryStream FillTemplate(DataSet mergedDataSet)
        {
            using (MemoryStream memoryStreamToOpen = new MemoryStream())
            {
                using (FileStream fstream = new FileStream(HttpContext.Current.Server.MapPath(AdatszolgaltatasokResource.ItmAdatszolgaltatasFelnottOktatásUtvonalTemplateExcelUtvonal), FileMode.Open, FileAccess.Read))
                {
                    try
                    {
                        fstream.CopyTo(memoryStreamToOpen);
                    }
                    catch (Exception)
                    {
                        fstream.Close();
                        throw;
                    }
                }

                Workbook workbook = new Workbook(memoryStreamToOpen);

                Worksheet alapadatFul = workbook.Worksheets[AdatszolgaltatasokResource.ItmAdatszolgaltatasKitoltendoExcelSheetNeve];

                var currentRow = 3;

                foreach (DataRow item in mergedDataSet.Tables[0].Rows)
                {
                    alapadatFul.Cells.ImportDataRow(item, currentRow++, 2);
                }

                workbook.CalculateFormula();

                var memoryStreamToSave = new MemoryStream();

                workbook.Save(memoryStreamToSave, SaveFormat.Xlsx);
                memoryStreamToSave.Position = 0;

                return memoryStreamToSave;
            }
        }

        private DataSet GetItmAdatok()
        {
            return Dal.CustomConnection.Run(ConnectionType, h =>
            {
                var dal = h.IntezmenyDal();
                return dal.GetIntezmenyItmAdatszolgaltatasAdatok(IntezmenyId, TanevId);
            });
        }

        private string IntezmenyFenntarto()
        {
            using (FileStream fstream = new FileStream(HttpContext.Current.Server.MapPath(AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaImportExcelUtvonal), FileMode.Open, FileAccess.Read))
            {
                try
                {
                    Workbook workbook = new Workbook(fstream);

                    Worksheet intezmenyLap = workbook.Worksheets[0];
                    DataTable intezmenyDataTable = intezmenyLap.Cells.ExportDataTable(0, 4, intezmenyLap.Cells.MaxDataRow, 2, true);

                    Worksheet fenntartoLap = workbook.Worksheets[2];
                    DataTable fenntartoDataTable = fenntartoLap.Cells.ExportDataTable(0, 0, fenntartoLap.Cells.MaxDataRow, 3, true);

                    ValidateDataTable(intezmenyDataTable, new List<string>() { AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelFenntarto, AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelIntezmenyAzonosito });
                    ValidateDataTable(fenntartoDataTable, new List<string>() { AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelAzonosito, AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelRovidnev });

                    var intezmenyDataRow = (from DataRow dr in intezmenyDataTable.Rows where dr.Field<string>(AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelIntezmenyAzonosito).ReplaceMultipleSpacesAndTrim() == IntezmenyAzonosito select dr).FirstOrDefault();

                    if (intezmenyDataRow == null)
                    {
                        throw new BlException(string.Format(AdatszolgaltatasokResource.ItmAdatszolgaltatasIsmeretlenIntezmenyAzonosito, IntezmenyAzonosito));
                    }

                    var fenntartoId = intezmenyDataRow.Field<double>(AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelFenntarto);

                    var fenntartoDataRow = (from DataRow dr in fenntartoDataTable.Rows where dr.Field<double>(AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelAzonosito) == fenntartoId select dr).FirstOrDefault();

                    if (fenntartoDataRow == null)
                    {
                        throw new BlException(string.Format(AdatszolgaltatasokResource.ItmAdatszolgaltatasIsmeretlenFenntartoAzonosito, fenntartoId));
                    }

                    var fenntartoNev = fenntartoDataRow.Field<string>(AdatszolgaltatasokResource.ItmAdatszolgaltatasIntezmenyListaExcelRovidnev).ReplaceMultipleSpacesAndTrim();

                    return fenntartoNev;
                }
                catch (Exception)
                {
                    fstream.Close();
                    throw;
                }
            }
        }

        private void ValidateDataTable(DataTable dataTable, List<string> columnName)
        {
            columnName.ForEach(x =>
            {
                if (!dataTable.Columns.Contains(x))
                {
                    throw new Exception();
                }
            });
        }
    }
}