using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace AdvertsingProfitControl
{
    public partial class frmDeleteRecord : Form
    {
        readonly LogConsole _console = LogConsole.GetStaticInstance;
        private List<string> _gDateStringCollection = new List<string>();
        private string _LastComment = "";

        public frmDeleteRecord()
        {
            InitializeComponent();
        }

        private void frmDeleteRecord_Load(object sender, EventArgs e)
        {
            FillDateSuggestionComboBoxes();
            BuildAndFillDataGridViews();

            //Setup event handlers
            projectionsDataGridView.UserDeletingRow += ClearRecordFromDatabaseOnRemoving;
            inventoryDataGridView.UserDeletingRow += ClearRecordFromDatabaseOnRemoving;
            actualSalesDataGridView.UserDeletingRow += ClearRecordFromDatabaseOnRemoving;
            suppliersDataGridView.UserDeletingRow += ClearInvoiceFromDatabaseOnRemoving;
            commentsTextBox.Leave += UpdateCommentsOnLeave;
        }

        /// <summary>
        /// Event USed: UserDeletingRow
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ClearInvoiceFromDatabaseOnRemoving(object sender, DataGridViewRowCancelEventArgs e)
        {
            var dataGridView = (DataGridView) sender;
            var databaseReader = new RetrieveFromDatabase();
            var databaseTracker = new DatabaseTracker();
            var databaseWriter = new DatabaseWriter(databaseTracker.DatabaseConnectionString);

            var dateId = databaseReader.RetrieveDateIdByDateString(monthComboBox.Text + "/" + dayComboBox.Text + "/" + yearComboBox.Text);
            if (dateId == "-1")
            {
                informationLabel.Text = "An error has occurred trying to obtain the ID\nfor the date " +
                                        monthComboBox.Text + "/" + dayComboBox.Text + "/" + yearComboBox.Text + ".";
            }
            var supplierName = dataGridView.Rows[e.Row.Index].Cells[0].EditedFormattedValue.ToString();
            var invoiceNumber = dataGridView.Rows[e.Row.Index].Cells[1].EditedFormattedValue.ToString();
            var count = databaseWriter.RemoveInvoice(invoiceNumber, dateId);

            if (count == 1)
            {
                informationLabel.Text = "Successfully removed the invoice from " + supplierName +
                                        " with\nthe invoice number of " + invoiceNumber + ".";
            }
            else if(count == 0)
            {
                informationLabel.Text = "Failed to remove the invoice from " + supplierName + " from the database.";
                e.Cancel = true;
            }
        }

        /// <summary>
        /// Event Used: Leave
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UpdateCommentsOnLeave(object sender, EventArgs e)
        {
            var databaseReader = new RetrieveFromDatabase();
            var databaseTracker = new DatabaseTracker();
            var datbaseWriter = new DatabaseWriter(databaseTracker.DatabaseConnectionString);

            if (commentsTextBox.Text == _LastComment)
            {
                return;
            }

            var dateId =
    databaseReader.RetrieveDateIdByDateString(monthComboBox.Text + "/" + dayComboBox.Text + "/" +
                                              yearComboBox.Text);
            if (dateId == "-1"){ informationLabel.Text = "unable to find date in database."; return; }
            var recordsAffected = datbaseWriter.UpdateCommentsByDateId(commentsTextBox.Text, dateId);
            if (recordsAffected == true)
            {
                informationLabel.Text = "Successfully updated the comments for the selected date.";
            }
            else
            {
                informationLabel.Text = "Failed to update the comments for the selected date.";
            }
            _LastComment = commentsTextBox.Text;

        }

        /// <summary>
        /// Event Used: UserDeletingRow
        /// Clears the record in the row being deleted from the database.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ClearRecordFromDatabaseOnRemoving(object sender, DataGridViewRowCancelEventArgs e)
        {
            var dataGridView = (DataGridView) sender;
            var dataBaseReader = new RetrieveFromDatabase();
            var tracker = new DatabaseTracker();
            var databaseWriter = new DatabaseWriter(tracker.DatabaseConnectionString);

            var dateId = dataBaseReader.RetrieveDateIdByDateString(monthComboBox.Text + "/" + dayComboBox.Text + "/" + yearComboBox.Text);
            var adItemName = e.Row.Cells[0].EditedFormattedValue.ToString();
            var adItemId = dataBaseReader.RetrieveAdItemId(adItemName);
            var count = databaseWriter.RemoveRecord(adItemId, dateId);

            if (count == 1)
            {
                informationLabel.Text = "Successfully removed " + adItemName + " from the database.";
                //
                projectionsDataGridView.UserDeletingRow -= ClearRecordFromDatabaseOnRemoving;
                inventoryDataGridView.UserDeletingRow -= ClearRecordFromDatabaseOnRemoving;
                actualSalesDataGridView.UserDeletingRow -= ClearRecordFromDatabaseOnRemoving;
                //Maybe make this based on tab page index.
                if (dataGridView.Name == "projectionsDataGridView")
                {
                    inventoryDataGridView.Rows.RemoveAt(e.Row.Index);
                    actualSalesDataGridView.Rows.RemoveAt(e.Row.Index);
                }
                else if (dataGridView.Name == "inventoryDataGridView")
                {
                    projectionsDataGridView.Rows.RemoveAt(e.Row.Index);
                    actualSalesDataGridView.Rows.RemoveAt(e.Row.Index);
                }
                else if (dataGridView.Name == "actualSalesDataGridView")
                {
                    projectionsDataGridView.Rows.RemoveAt(e.Row.Index);
                    inventoryDataGridView.Rows.RemoveAt(e.Row.Index);
                }
            }
            else
            {
                informationLabel.Text = "Failed to remove " + adItemName + " from the database.";
                e.Cancel = true;
            }

            projectionsDataGridView.UserDeletingRow += ClearRecordFromDatabaseOnRemoving;
            inventoryDataGridView.UserDeletingRow += ClearRecordFromDatabaseOnRemoving;
            actualSalesDataGridView.UserDeletingRow += ClearRecordFromDatabaseOnRemoving;
        }


        private void UpdateDataGridViewInformation(object sender, EventArgs e)
        {
            string dateString = monthComboBox.Text + "/" + dayComboBox.Text + "/" + yearComboBox.Text;
            BuildAndFillDataGridViews(dateString);
        }

        private void BuildAndFillDataGridViews(string dateString = "")
        {
            var dataBaseReader = new RetrieveFromDatabase();

            var dateId = "";

            //Check to see if a parameter has been passed.
            if (dateString == "")
            {
                //IF non were, then grab the most recent date ID from the database and use that.
                dateId = dataBaseReader.RetrieveMostRecentDateId();
                _console.WriteToLog(LogConsole.Level.Info, dateId != "-1" ? "Most recent date ID is " + dateId : "Most recent date ID is unavailable.");
            }
            else
            {
                //ELSE IF one was passed, then use it's ID to build the tables.
                dateId = dataBaseReader.RetrieveDateIdByDateString(dateString);
                _console.WriteToLog(LogConsole.Level.Info, dateId != "-1" ? "Date ID for " + dateString + " is resolved to have the ID of " + dateId + "." : "The date " + dateString + " could not be found in the database.");
                if (dateId == "-1")
                {
                    _gDateStringCollection.Remove(dateString);
                }
            }
            //Now check to make sure there were no errors grabbing the ID, IF there were return.
            if (dateId == "-1") return;
            //Clear all DataGridViews since the date supplied is valid and in the database.
            projectionsDataGridView.DataSource = null;
            inventoryDataGridView.DataSource = null;
            actualSalesDataGridView.DataSource = null;
            suppliersDataGridView.DataSource = null;
            weeklySalesDataGridView.DataSource = null;
            //Fill the tables from the database.
            projectionsDataGridView.DataSource = CleanDataTable(dataBaseReader.ReturnProjectionsTable(dateId));
            inventoryDataGridView.DataSource = CleanDataTable(dataBaseReader.ReturnInventoryTable(dateId));
            actualSalesDataGridView.DataSource = CleanDataTable(dataBaseReader.ReturnActualSales(dateId));
            suppliersDataGridView.DataSource = dataBaseReader.ReturnInvoiceTable(dateId);
            weeklySalesDataGridView.DataSource = dataBaseReader.ReturnWeeklySalesFromDateID(dateId);

            commentsTextBox.Text = dataBaseReader.RetrieveComments(dateId);
            if (commentsTextBox.Text.StartsWith("No comments"))
            {
                commentsTextBox.Enabled = false;
            }
            else
            {
                commentsTextBox.Enabled = true;  
                _LastComment = commentsTextBox.Text; 
            }           
        }

        private DataTable CleanDataTable(DataTable table)
        {
            var cleanedTable = new DataTable();

            if (table.Columns[table.Columns.Count - 1].ColumnName == "FK_GroupID")
            {
                table.Columns.RemoveAt(table.Columns.Count - 1);
            }

            cleanedTable = table;

            return cleanedTable;
        }

        /// <summary>
        /// Grabs all dates from the database and splits the returned strings 
        /// into months, days, and years and stores them in their respective 
        /// combo boxes to display to the user. Also stores the list of dates
        /// inside a class wide variable.
        /// </summary>
        private void FillDateSuggestionComboBoxes()
        {
            //Create a connection to the database retrieval class.
            var dbReader = new RetrieveFromDatabase();
            //Grab the most recent date in the database.
            var mostRecentDateTime = dbReader.ReturnMostRecentDateString();
            var mostRecentDateString = mostRecentDateTime.ToString("MM/dd/yyyy");
            //Check to see if the return value is null and IF so log the error and return.
            if (mostRecentDateString == "") { _console.WriteToLog(LogConsole.Level.Error, "No dates could be found in the database."); return; }
            //Otherwise, if there was a return date, split it into a array.
            var mostRecentDateParts = mostRecentDateString.Split('/');
            //Grab only the most recent years in the database (only say 2015) and fill a table with the dates. Indexes are as follows: [0] is Month, [1] is Day and [2] is Year.
            DataTable oneYearDatesTable = dbReader.ReturnDateStringsLike(mostRecentDateParts[0] + "/" + mostRecentDateParts[1] + "/" + mostRecentDateParts[2]);
            //Suspend the control's drawing so the user doesn't see any ugly enumeration and index changing.
            DrawingControl.SuspendDrawing(secondaryLayOutPanel);
            //Considering there was a return value for the most recent date, its safe to assume there is at least one date in the database, so clear the class's date collection.
            _gDateStringCollection.Clear();
            monthComboBox.Items.Clear();
            dayComboBox.Items.Clear();
            yearComboBox.Items.Clear();
            monthComboBox.SelectedIndexChanged -= UpdateDaysOfMonth;
            dayComboBox.SelectedIndexChanged -= UpdateDataGridViewInformation;
            yearComboBox.SelectedIndexChanged -= UpdateDaysOfMonthByYear;
            //Now spin through the oneYearDatesTable and fill the class wide object with all the dates for the most recent year.
            for (var i = 0; i < oneYearDatesTable.Rows.Count; i++)
            {
                var fullDateTime = (DateTime)oneYearDatesTable.Rows[i][0];
                var fullDateString = fullDateTime.ToString("MM/dd/yyyy");
                //Check for nulls just to be paranoid.
                if (fullDateString == "")
                {
                    return;
                }
                //IF the date string collection already contains the date, then continue to the next iteration.
                if (_gDateStringCollection.Contains(fullDateString))
                {
                    continue;
                }
                _gDateStringCollection.Add(fullDateString);
            }

            var dayBasedOnMonthAndYeaRegex = new Regex("^0?" + mostRecentDateParts[0] + @"/\d{2}/" + mostRecentDateParts[2]);
            var monthBasedOnYearRegex = new Regex(@"^\d{2}/\d{2}/" + mostRecentDateParts[2]);
            for (var i = 0; i < _gDateStringCollection.Count; i++)
            {
                string[] dateArray = _gDateStringCollection[i].Split('/');
                var month = dateArray[0];
                var day = dateArray[1];

                if (dayBasedOnMonthAndYeaRegex.IsMatch(_gDateStringCollection[i]))
                {
                    dayComboBox.Items.Add(day);
                }
                if (monthBasedOnYearRegex.IsMatch(_gDateStringCollection[i]))
                {
                    if (!monthComboBox.Items.Contains(month))
                    {
                        monthComboBox.Items.Add(month);
                    }
                }
            }

            var yearsInDatabase = dbReader.ReturnUniqueYearsList();

            foreach (var year in yearsInDatabase)
            {
                yearComboBox.Items.Add(year);
            }

            if (dayComboBox.Items.Count >= 1 && yearComboBox.Items.Count >= 1 && monthComboBox.Items.Count >= 1)
            {
                monthComboBox.SelectedIndex = monthComboBox.Items.Count - 1;
                dayComboBox.SelectedIndex = dayComboBox.Items.Count - 1;
                yearComboBox.SelectedIndex = yearComboBox.Items.Count - 1;
                monthComboBox.Enabled = true;
                dayComboBox.Enabled = true;
                yearComboBox.Enabled = true;
            }
            else
            {
                monthComboBox.Enabled = false;
                dayComboBox.Enabled = false;
                yearComboBox.Enabled = false;
            }
            monthComboBox.SelectedIndexChanged += UpdateDaysOfMonth;
            dayComboBox.SelectedIndexChanged += UpdateDataGridViewInformation;
            yearComboBox.SelectedIndexChanged += UpdateDaysOfMonthByYear;
            DrawingControl.ResumeDrawing(secondaryLayOutPanel);
        }


        private void UpdateDaysOfMonth(object sender, EventArgs e)
        {
            if (yearComboBox.SelectedIndex == -1) return;
            var year = yearComboBox.SelectedItem.ToString();
            var month = monthComboBox.SelectedItem.ToString();
            var dateParserPattern = new Regex("^" + month + @"\/\d{2}\/" + year);

            dayComboBox.Items.Clear();

            for (var i = 0; i < _gDateStringCollection.Count; i++)
            {
                if (dateParserPattern.IsMatch(_gDateStringCollection[i]))
                {
                    var dateArray = _gDateStringCollection[i].Split('/');
                    var day = dateArray[1];
                    dayComboBox.Items.Add(day);
                }
            }

            if (dayComboBox.Items.Count > 0)
            {
                dayComboBox.SelectedIndex = dayComboBox.Items.Count - 1;
            }
        }
        /// <summary>
        /// Fires when the Year combo box's index changes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UpdateDaysOfMonthByYear(object sender, EventArgs e)
        {
            //Obligatory database retrieval call...
            var dbReader = new RetrieveFromDatabase();
            //First, grab the year and the month from their respective combo boxes.
            var year = yearComboBox.SelectedItem.ToString();
            var month = monthComboBox.SelectedItem.ToString();
            //Since we can more or less be certain that nothing is null, clear the current date collection.
            _gDateStringCollection.Clear();
            var months = dbReader.ReturnUniqueMonthsList(month + "/" + dayComboBox.SelectedItem + "/" + year);
            var mostRecentMonth = months.Max();
            if (mostRecentMonth.Length == 1)
            {
                mostRecentMonth = "0" + mostRecentMonth;
            }
            var selectedYearDates = dbReader.ReturnDateStringsLike(month + "/" + dayComboBox.SelectedItem + "/" + year);

            for (var i = 0; i < selectedYearDates.Rows.Count; i++)
            {
                var trimmedDateString = (DateTime)selectedYearDates.Rows[i][0];
                _gDateStringCollection.Add(trimmedDateString.ToString("MM/dd/yyyy"));
            }

            //Clear the month and day combo boxes and unregister their event handlers.
            dayComboBox.Items.Clear();
            monthComboBox.Items.Clear();
            monthComboBox.SelectedIndexChanged -= UpdateDaysOfMonth;
            dayComboBox.SelectedIndexChanged -= UpdateDataGridViewInformation;
            for (var i = 0; i < _gDateStringCollection.Count; i++)
            {
                var dateArray = _gDateStringCollection[i].Split('/');
                month = dateArray[0];
                //Declare the patterns to look for when enumerating the combo boxes.
                var dayBasedOnMonthAndYeaRegex = new Regex(@"^(" + mostRecentMonth + @"\/\d{2}\/" + year + ")"); //Only allows days that are actually part of the month and year.
                var day = dateArray[1];

                if (dayBasedOnMonthAndYeaRegex.IsMatch(_gDateStringCollection[i]))
                {
                    dayComboBox.Items.Add(day);
                }

                if (!monthComboBox.Items.Contains(month))
                {
                    monthComboBox.Items.Add(month);
                }
            }

            if (dayComboBox.Items.Count > 0)
            {
                dayComboBox.SelectedIndex = dayComboBox.Items.Count - 1;
            }
            if (monthComboBox.Items.Count > 0)
            {
                monthComboBox.SelectedIndex = monthComboBox.Items.Count - 1;
            }

            //Now re-register the event handlers
            monthComboBox.SelectedIndexChanged += UpdateDaysOfMonth;
            dayComboBox.SelectedIndexChanged += UpdateDataGridViewInformation;

            BuildAndFillDataGridViews(monthComboBox.SelectedItem + "/" + dayComboBox.SelectedItem + "/" + year);
        }

        private void DELETE_Click(object sender, EventArgs e)
        {
            var databaseReader = new RetrieveFromDatabase();
            var databaseTracker = new DatabaseTracker();
            var databaseWriter = new DatabaseWriter(databaseTracker.DatabaseConnectionString);

            var result = MessageBox.Show("Are you sure you wish to delete all records for the date selected date (" + monthComboBox.Text +"/" + dayComboBox.Text + "/" + yearComboBox.Text + ")?\nThis cannot be undone.", "Purge Selected Year", MessageBoxButtons.YesNo)
            ;
            if (result == DialogResult.Yes)
            {
                var dateId =
                    databaseReader.RetrieveDateIdByDateString(monthComboBox.Text + "/" + dayComboBox.Text + "/" +
                                                              yearComboBox.Text);
                var recordsAffected = databaseWriter.RemoveAllEntriesAndYearById(dateId);
                if (recordsAffected > 0)
                {
                    informationLabel.Text = "Successfully removed " + recordsAffected.ToString() +
                                            " entries clearing all records of\n" + monthComboBox.Text + "/" + dayComboBox.Text +
                                            "/" + yearComboBox.Text + " from the database.";
                }
            }
            else
            {
                return;
            }
            FillDateSuggestionComboBoxes();
            BuildAndFillDataGridViews();
        }
    }
}
