using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AdvertsingProfitControl
{
    public partial class DebugDatabaseConverter : Form
    {
        private string _filePath;
        private string _connectionString;
        public DebugDatabaseConverter()
        {
            InitializeComponent();
            existingDatesListBox.SelectedIndexChanged += EnableButton;
        }

        private void EnableButton(object sender, EventArgs e)
        {
            moveOverButton.Enabled = true;
        }

        private void DebugDatabaseConverter_Load(object sender, EventArgs e)
        {
            openFileDialog1.DefaultExt = "accdb";
            openFileDialog1.Filter = @"Access Files (*.accdb) | *.accdb";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                var filePath = openFileDialog1.FileName;
                if (File.Exists(filePath))
                {
                    _filePath = filePath;
                    //Get the list of dates.
                    var connectionString =
                        "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Persist Security Info=False";
                    _connectionString = connectionString;
                    var dates = new List<DateTime>();
                    var oleDbCommand = new OleDbCommand
                    {
                        CommandText = "SELECT EndOfWeekDate FROM WeekEnding"
                    };
                    var connection = new OleDbConnection(connectionString);
                    oleDbCommand.Connection = connection;

                    using (connection)
                    {
                        using (oleDbCommand)
                        {
                            connection.Open();
                            using (var reader = oleDbCommand.ExecuteReader())
                            {
                                while (reader != null && reader.Read())
                                {
                                    dates.Add(DateTime.Parse(reader[0].ToString()));
                                }
                            }
                        }
                        connection.Close();
                    }

                    foreach (var date in dates)
                    {
                        existingDatesListBox.Items.Add(date.ToShortDateString());
                    }
                }
            }
        }

        private void moveOverButton_Click(object sender, EventArgs e)
        {
            if (existingDatesListBox.SelectedIndex != -1)
            {
                datesToConvertListBox.Items.Add(existingDatesListBox.SelectedItem);
                existingDatesListBox.Items.Remove(existingDatesListBox.SelectedItem);
                moveOverButton.Enabled = false;
            }
        }

        private void convertButton_Click(object sender, EventArgs e)
        {
            if (datesToConvertListBox.Items.Count == 0)
            {
                return;
            }
            foreach (var date in datesToConvertListBox.Items)
            {
                var oldDateId = GetDateIdByDateString(date.ToString());
                //Get the tables.
                var projectionsTable = ReturnProjections(oldDateId);
                var inventoryTable = ReturnInventory(oldDateId);
                var actualSales = ReturnActualSales(oldDateId);
                var invoices = ReturnInvoiceTable(oldDateId);
                var weeklySales = ReturnWeeklySalesFromDateId(oldDateId);
                var comment = GetComments(oldDateId);
                MassiveWriteFunction(date.ToString(), projectionsTable, inventoryTable, actualSales, invoices, weeklySales, comment);
            }
        }

        private void MassiveWriteFunction(string dateString, DataTable projections, DataTable inventory, DataTable actualSales, DataTable invoice, DataTable weeklySales, string comments)
        {
            var dbT = new DatabaseTracker();
            //Get a new ID number for the date supplied.
            var oleDbConnection = new OleDbConnection(dbT.DatabaseConnectionString);
            var oleDbCommand = new OleDbCommand
            {
                Connection = oleDbConnection
            };
            OleDbTransaction oleDbTransaction = null;
            try
            {
                oleDbConnection.Open();
                oleDbTransaction = oleDbConnection.BeginTransaction();
                oleDbCommand.Transaction = oleDbTransaction;
                //Get the date ID for the date string
                oleDbCommand.CommandText = "INSERT INTO WeekEnding (EndOfWeekDate) VALUES (?)";
                oleDbCommand.Parameters.AddWithValue("DateString", dateString);
                var rowsEffected = oleDbCommand.ExecuteNonQuery();
                oleDbCommand.Parameters.Clear();
                if (rowsEffected == 0)
                {
                    oleDbTransaction.Rollback();
                    MessageBox.Show(@"Failed on date");
                    return;
                }
                oleDbCommand.CommandText = "SELECT WeekEnding.ID FROM WeekEnding WHERE EndOfWeekDate = ?";
                oleDbCommand.Parameters.AddWithValue("Date", dateString);
                var reader = oleDbCommand.ExecuteReader();
                oleDbCommand.Parameters.Clear();
                var dateId = 0;
                while (reader != null && reader.Read())
                {
                    dateId = int.Parse(reader[0].ToString());
                }
                reader?.Close();
                int adspecialId = 0;
                for (var rowIndex = 0; rowIndex < projections.Rows.Count; rowIndex++)
                {
                    //Get the ID number of the ad item.
                    var adItemId = int.Parse(RetrieveAdItemId(projections.Rows[rowIndex][0].ToString()));
                    //Get the group name of the ad special its in.
                    adspecialId = GetAdSpecialId(int.Parse(projections.Rows[rowIndex][8].ToString()));
                    oleDbCommand.CommandText =
                        "INSERT INTO Projections (Sold, SalePrice, TotalSales, Cost, ProfitReturn, TotalProfitReturn, FK_AdItemID, RowAttribute, FK_AdSpecialGroupName, RowPosition, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
                    //SELECT AdItem.AdItem, APC.ProjectionSold, APC.ProjectionSalePrice, APC.ProjectionTotalSales, APC.ProjectionCost, APC.ProjectionProfitReturn, APC.ProjectionTotalProfitReturn, APC.RowAttribute, APC.FK_GroupID FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC
                    oleDbCommand.Parameters.AddWithValue("Sold", projections.Rows[rowIndex][1]);
                    oleDbCommand.Parameters.AddWithValue("SalesPrice", projections.Rows[rowIndex][2]);
                    oleDbCommand.Parameters.AddWithValue("TotalSales", projections.Rows[rowIndex][3]);
                    oleDbCommand.Parameters.AddWithValue("Cost", projections.Rows[rowIndex][4]);
                    oleDbCommand.Parameters.AddWithValue("ProfitReturn", projections.Rows[rowIndex][5]);
                    oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", projections.Rows[rowIndex][6]);
                    oleDbCommand.Parameters.AddWithValue("adItemID", adItemId);
                    oleDbCommand.Parameters.AddWithValue("RowAttribute",
                        int.Parse(projections.Rows[rowIndex][7].ToString()));
                    oleDbCommand.Parameters.AddWithValue("adSpecialID", adspecialId);
                    oleDbCommand.Parameters.AddWithValue("RowPosition", (rowIndex + 1));
                    oleDbCommand.Parameters.AddWithValue("dateID", dateId);
                    oleDbCommand.ExecuteNonQuery();
                    oleDbCommand.Parameters.Clear();
                }
                //inventory
                for (var i = 0; i < inventory.Rows.Count; i++)
                {
                    var adItemId = int.Parse(RetrieveAdItemId(inventory.Rows[i][0].ToString()));
                    adspecialId = GetAdSpecialId(int.Parse(inventory.Rows[i][6].ToString()));
                    oleDbCommand.CommandText =
                        "INSERT INTO Inventory (BeginningInventory, Received, TotalInventory, EndingInventory, FK_AdItemID, RowAttribute, FK_AdSpecialGroupName, RowPosition, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
                    //"SELECT AdItem.AdItem, APC.BeginingInventory, APC.Received, APC.TotalInventory, APC.EndingInventory, APC.RowAttribute, APC.FK_GroupID FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
                    oleDbCommand.Parameters.AddWithValue("BeginningInventory", inventory.Rows[i][1].ToString());
                    oleDbCommand.Parameters.AddWithValue("Received", inventory.Rows[i][2].ToString());
                    oleDbCommand.Parameters.AddWithValue("TotalInventory", inventory.Rows[i][3].ToString());
                    oleDbCommand.Parameters.AddWithValue("EndingInventory", inventory.Rows[i][4].ToString());
                    oleDbCommand.Parameters.AddWithValue("AdItemID", adItemId);
                    oleDbCommand.Parameters.AddWithValue("RowAttribute", int.Parse(inventory.Rows[i][5].ToString()));
                    oleDbCommand.Parameters.AddWithValue("FK_AdSpecialGroup", adspecialId);
                    oleDbCommand.Parameters.AddWithValue("RowPosition", (i + 1));
                    oleDbCommand.Parameters.AddWithValue("DateID", dateId);
                    oleDbCommand.ExecuteNonQuery();
                    oleDbCommand.Parameters.Clear();
                }

                //actual sales
                for (var rowIndex = 0; rowIndex < actualSales.Rows.Count; rowIndex++)
                {
                    //Get the ID number of the ad item.
                    var adItemId = int.Parse(RetrieveAdItemId(actualSales.Rows[rowIndex][0].ToString()));
                    adspecialId = GetAdSpecialId(int.Parse(actualSales.Rows[rowIndex][8].ToString()));
                    oleDbCommand.CommandText =
                        "INSERT INTO ActualSales (Sold, SalePrice, TotalSales, Cost, ProfitReturn, TotalProfitReturn, FK_AdItemID, RowAttribute, FK_AdSpecialGroupName, RowPosition, FK_DateID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
                    //SELECT AdItem.AdItem, APC.ProjectionSold, APC.ProjectionSalePrice, APC.ProjectionTotalSales, APC.ProjectionCost, APC.ProjectionProfitReturn, APC.ProjectionTotalProfitReturn, APC.RowAttribute, APC.FK_GroupID FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC
                    oleDbCommand.Parameters.AddWithValue("Sold", actualSales.Rows[rowIndex][1]);
                    oleDbCommand.Parameters.AddWithValue("SalesPrice", actualSales.Rows[rowIndex][2]);
                    oleDbCommand.Parameters.AddWithValue("TotalSales", actualSales.Rows[rowIndex][3]);
                    oleDbCommand.Parameters.AddWithValue("Cost", actualSales.Rows[rowIndex][4]);
                    oleDbCommand.Parameters.AddWithValue("ProfitReturn", actualSales.Rows[rowIndex][5]);
                    oleDbCommand.Parameters.AddWithValue("TotalProfitReturn", actualSales.Rows[rowIndex][6]);
                    oleDbCommand.Parameters.AddWithValue("adItemID", adItemId);
                    oleDbCommand.Parameters.AddWithValue("RowAttribute",
                        int.Parse(projections.Rows[rowIndex][7].ToString()));
                    oleDbCommand.Parameters.AddWithValue("adSpecialID", adspecialId);
                    oleDbCommand.Parameters.AddWithValue("RowPosition", (rowIndex + 1));
                    oleDbCommand.Parameters.AddWithValue("dateID", dateId);
                    oleDbCommand.ExecuteNonQuery();
                    oleDbCommand.Parameters.Clear();
                }

                for (var i = 0; i < invoice.Rows.Count; i++)
                {
                    var supplierId = GetSupplierId(invoice.Rows[i][1].ToString());
                    //SELECT Invoice.InvoiceDate, Supplier.SupplierName, Invoice.InvoiceNumber,  Invoice.InvoiceNetAmountAtCost, Invoice.InvoiceNetAmount, Invoice.InvoiceNote FROM (Supplier INNER JOIN Invoice ON Supplier.ID = Invoice.FK_Supplier) WHERE FK_DateID = ?
                    oleDbCommand.CommandText =
                        "INSERT INTO Invoice (InvoiceDate, InvoiceNumber, InvoiceNetAmountAtCost, InvoiceNetAmount, InvoiceNote, FK_Supplier, FK_DateID) VALUES(?,?,?,?,?,?,?)";
                    oleDbCommand.Parameters.AddWithValue("InvoiceDate", invoice.Rows[i][0].ToString());
                    oleDbCommand.Parameters.AddWithValue("InvoiceNumber", invoice.Rows[i][2].ToString());
                    oleDbCommand.Parameters.AddWithValue("InvoiceNetAmountAtCost",
                        invoice.Rows[i][3].ToString() == "" ? 0 : double.Parse(invoice.Rows[i][3].ToString()));
                    oleDbCommand.Parameters.AddWithValue("InvoiceNetAmount",
                        invoice.Rows[i][4].ToString() == "" ? 0 : double.Parse(invoice.Rows[i][4].ToString()));
                    oleDbCommand.Parameters.AddWithValue("InvoiceNote", invoice.Rows[i][5].ToString());
                    oleDbCommand.Parameters.AddWithValue("FK_Supplier", supplierId);
                    oleDbCommand.Parameters.AddWithValue("FK_DateID", dateId);
                    oleDbCommand.ExecuteNonQuery();
                    oleDbCommand.Parameters.Clear();
                }
                //"SELECT WeeklySales.Sunday, WeeklySales.Monday, WeeklySales.Tuesday, WeeklySales.Wednesday, WeeklySales.Thursday, WeeklySales.Friday, WeeklySales.Saturday, WeeklySales.TotalSales FROM WeeklySales WHERE FK_DateID = ?"
                oleDbCommand.CommandText =
                    "INSERT INTO WeeklySales (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, TotalSales, FK_DateID) VALUES (?,?,?,?,?,?,?,?,?)";
                oleDbCommand.Parameters.AddWithValue("Sunday", weeklySales.Rows[0][0]);
                oleDbCommand.Parameters.AddWithValue("Monday", weeklySales.Rows[0][1]);
                oleDbCommand.Parameters.AddWithValue("Tuesday", weeklySales.Rows[0][2]);
                oleDbCommand.Parameters.AddWithValue("Wednesday", weeklySales.Rows[0][3]);
                oleDbCommand.Parameters.AddWithValue("Thursday", weeklySales.Rows[0][4]);
                oleDbCommand.Parameters.AddWithValue("Friday", weeklySales.Rows[0][5]);
                oleDbCommand.Parameters.AddWithValue("Saturday", weeklySales.Rows[0][6]);
                oleDbCommand.Parameters.AddWithValue("TotalSales", weeklySales.Rows[0][7]);
                oleDbCommand.Parameters.AddWithValue("DateID", dateId);
                oleDbCommand.ExecuteNonQuery();

                oleDbCommand.Parameters.Clear();
                oleDbCommand.CommandText = "INSERT INTO Comment (Comment, FK_DateID) VALUES (?, ?)";
                oleDbCommand.Parameters.AddWithValue("Com", comments);
                oleDbCommand.Parameters.AddWithValue("FK", dateId);
                oleDbCommand.ExecuteNonQuery();
                oleDbTransaction.Commit();             
            }
            catch (OleDbException e)
            {
                MessageBox.Show(e.Message);
                oleDbTransaction?.Rollback();
            }
            finally
            {
                oleDbConnection.Close();
            }
        }

        public int GetSupplierId(string supplierName)
        {
            var dbT = new DatabaseTracker();
            var supplierId = 0;
            var oleDbConnection = new OleDbConnection(dbT.DatabaseConnectionString);
            var oleDbCommand = new OleDbCommand
            {
                Connection = oleDbConnection,
                CommandText = "SELECT Supplier.ID FROM Supplier WHERE SupplierName = ?"
            };
            oleDbCommand.Parameters.AddWithValue("eh", supplierName);

            try
            {
                oleDbConnection.Open();
                var reader = oleDbCommand.ExecuteReader();
                while (reader != null && reader.Read())
                {
                    supplierId = int.Parse(reader[0].ToString());
                }
            }
            catch (OleDbException e)
            {
                MessageBox.Show(e.Message);
            }
            finally
            {
                oleDbConnection.Close();
            }
            return supplierId;
        }

        public int GetAdSpecialId(int adSpecialId)
        {
            var id = 0;
            var dbT = new DatabaseTracker();
            var dbR = new DatabaseReader();
            //Get a new ID number for the date supplied.
            var oleDbConnection = new OleDbConnection(_connectionString);
            var oleDbCommand = new OleDbCommand
            {
                Connection = oleDbConnection,
                CommandText = "SELECT GroupCategory.GroupDescription FROM GroupCategory WHERE GroupCategory.ID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("eh", adSpecialId);

            try
            {
                oleDbConnection.Open();
                var reader = oleDbCommand.ExecuteReader();
                string adSpecialText = "";
                while (reader != null && reader.Read())
                {
                    adSpecialText = reader[0].ToString();
                }
                oleDbCommand.Parameters.Clear();
                oleDbCommand.Connection.Close();
                var spam = new OleDbConnection(dbT.DatabaseConnectionString);
                var newSpam = new OleDbCommand
                {
                    Connection = spam,
                    CommandText =
                        "SELECT AdSpecialName.ID FROM AdSpecialName WHERE AdSpecialName.AdSpecialName = ?"
                };
                spam.Open();
                newSpam.Parameters.AddWithValue("text", adSpecialText);
                reader?.Close();
                reader = newSpam.ExecuteReader();
                while (reader != null && reader.Read())
                {
                    id = int.Parse(reader[0].ToString());
                }
                reader?.Close();
                spam.Close();
            }
            catch (OleDbException e)
            {
                MessageBox.Show(e.Message);
                throw;
            }
            finally
            {
                oleDbConnection.Close();
            }
            return id;
        }

        private string GetComments(int dateId)
        {
            var comments = "";
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "SELECT Comment.Comment FROM Comment WHERE Comment.FK_DateID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;
            using (connection)
            {
                using (oleDbCommand)
                {
                    connection.Open();
                    var reader = oleDbCommand.ExecuteReader();
                    while (reader != null && reader.Read())
                    {
                        comments = reader[0].ToString();
                    }
                }
            }

            return comments;
        }

        public string RetrieveAdItemId(string adItemName)
        {
            var dbT = new DatabaseTracker();
            var dbR = new DatabaseReader();
            
            return dbR.RetrieveAdItemId(adItemName, dbT.DatabaseConnectionString);
        }

        private int GetDateIdByDateString(string dateString)
        {
            var dateId = 0;
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "SELECT WeekEnding.ID FROM WeekEnding WHERE WeekEnding.EndOfWeekDate = ?"
            };
            oleDbCommand.Parameters.AddWithValue("DateString", dateString);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;

            using (connection)
            {
                using (oleDbCommand)
                {
                    connection.Open();
                    using (var reader = oleDbCommand.ExecuteReader())
                    {
                        while (reader != null && reader.Read())
                        {
                            dateId = int.Parse(reader[0].ToString());
                        }
                    }
                }
                connection.Close();
            }

            return dateId;
        }

        private DataTable ReturnProjections(int dateId)
        {
            var dataTable = new DataTable();
            var oleDbCommand = new OleDbCommand
            {
                CommandText = "SELECT AdItem.AdItem, APC.ProjectionSold, APC.ProjectionSalePrice, APC.ProjectionTotalSales, APC.ProjectionCost, APC.ProjectionProfitReturn, APC.ProjectionTotalProfitReturn, APC.RowAttribute, APC.FK_GroupID FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
            };
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;

            using (connection)
            {
                using (oleDbCommand)
                {
                    connection.Open();
                    using (var dataAdapter = new OleDbDataAdapter(oleDbCommand))
                    {
                        dataAdapter.Fill(dataTable);
                    }
                }
                connection.Close();
            }
            return dataTable;
        }

        public DataTable ReturnInventory(int dateId)
        {
            var dataTable = new DataTable();
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "SELECT AdItem.AdItem, APC.BeginingInventory, APC.Received, APC.TotalInventory, APC.EndingInventory, APC.RowAttribute, APC.FK_GroupID FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
            };
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;

            using (connection)
            {
                using (oleDbCommand)
                {
                    connection.Open();
                    using (var dataAdapter = new OleDbDataAdapter(oleDbCommand))
                    {
                        dataAdapter.Fill(dataTable);
                    }
                }
                connection.Close();
            }
            return dataTable;
        }

        public DataTable ReturnActualSales(int dateId)
        {
            var dataTable = new DataTable();
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "SELECT AdItem.AdItem, APC.ActualSold, APC.ActualSalePrice, APC.ActualTotalSales, APC.ActualCost, APC.ActualProfitReturn, APC.ActualTotalProfitReturn, APC.RowAttribute, APC.FK_GroupID FROM (AdItem INNER JOIN APC ON AdItem.ID = APC.FK_AdItemID) WHERE FK_DateID = ? ORDER BY RowPosition ASC"
            };
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;

            using (connection)
            {
                using (oleDbCommand)
                {
                    connection.Open();
                    using (var dataAdapter = new OleDbDataAdapter(oleDbCommand))
                    {
                        dataAdapter.Fill(dataTable);
                    }
                }
                connection.Close();
            }
            return dataTable;
        }

        public DataTable ReturnInvoiceTable(int dateId)
        {
            var dataTable = new DataTable();
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "SELECT Invoice.InvoiceDate, Supplier.SupplierName, Invoice.InvoiceNumber,  Invoice.InvoiceNetAmountAtCost, Invoice.InvoiceNetAmount, Invoice.InvoiceNote FROM (Supplier INNER JOIN Invoice ON Supplier.ID = Invoice.FK_Supplier) WHERE FK_DateID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;

            using (connection)
            {
                using (oleDbCommand)
                {
                    using (var adapter = new OleDbDataAdapter(oleDbCommand))
                    {
                        adapter.Fill(dataTable);
                    }
                }
                connection.Close();
            }

            return dataTable;
        }

        public DataTable ReturnWeeklySalesFromDateId(int dateId)
        {
            var dataTable = new DataTable();
            var oleDbCommand = new OleDbCommand()
            {
                CommandText = "SELECT WeeklySales.Sunday, WeeklySales.Monday, WeeklySales.Tuesday, WeeklySales.Wednesday, WeeklySales.Thursday, WeeklySales.Friday, WeeklySales.Saturday, WeeklySales.TotalSales FROM WeeklySales WHERE FK_DateID = ?"
            };
            oleDbCommand.Parameters.AddWithValue("DateID", dateId);
            var connection = new OleDbConnection(_connectionString);
            oleDbCommand.Connection = connection;
            using (connection)
            {
                using (oleDbCommand)
                {
                    connection.Open();
                    using (var dataAdapter = new OleDbDataAdapter(oleDbCommand))
                    {
                        dataAdapter.Fill(dataTable);
                    }
                }
                connection.Close();
            }

            return dataTable;
        }
    }
}
